The next generation Cloud transcoding service.
The official Go library for the Chunkify API.
- Go 1.22 or higher
You can install the Chunkify Go library using go get
:
go get github.com/chunkifydev/chunkify-go
First, you'll need to create a client instance to interact with the API. You can create one with default settings or with custom configuration:
import "github.com/chunkifydev/chunkify-go"
// Create a new client instance with default settings
client := chunkify.NewClient(chunkify.AccessTokens{
TeamToken: "sk_team_token",
ProjectToken: "sk_project_token",
})
You can initialize the client with custom configuration:
config := chunkify.Config{
AccessTokens: chunkify.AccessTokens{
TeamToken: "sk_team_token",
ProjectToken: "sk_project_token",
},
Timeout: 60 * time.Second,
}
client = chunkify.NewClientWithConfig(config)
You will need to upload your file, to do so you first need to create an upload entry. This will enable the creation of a source from it upon upload completion:
// First create an upload entry
uploadResponse, err := client.UploadCreate(chunkify.UploadCreateParams{
Metadata: chunkify.UploadCreateParamsMetadata{
"key": "value",
},
})
if err != nil {
t.Fatalf("Error creating upload: %v", err)
}
// Open a file to upload
file, err := os.Open("path/to/your/file.mp4")
if err != nil {
log.Fatal(err)
}
defer file.Close()
// Upload the file using the obtained upload response
err = client.UploadBlob(context.TODO(), file, uploadResponse)
if err != nil {
log.Fatal(err)
}
// Upon successful upload a new source will be created.
If your file is already hosted online, you can create a source directly from its URL:
// Create a new source
source, err := client.SourceCreate(chunkify.SourceCreateParams{
Url: "http://somevideos.com/your_source.mp4",
Metadata: chunkify.SourceCreateParamsMetadata{
"key": "value",
},
})
if err != nil {
t.Fatalf("Error creating source: %v", err)
}
fmt.Printf("New source: %s (%dx%d) with codec %s\n", source.Id, source.Width, source.Height, source.VideoCodec)
Here is an example of job creation:
// Create a new job with a custom template
config := &chunkify.H264{
Video: &chunkify.Video{
Height: chunkify.Int64(1080),
Framerate: chunkify.Int64(30),
VideoBitrate: chunkify.Int64(5000000), // 5 Mbps
AudioBitrate: chunkify.Int64(128000), // 128 Kbps
},
}
// JobCreateFormatParams has a field for each supported format
// You must use the appropriate field for the format you want to use
job, err := client.JobCreate(chunkify.JobCreateParams{
SourceId: source.Id,
Format: chunkify.JobCreateFormatParams{
Mp4H264: config,
},
})
// If you want to use an encoding format but with no specific parameters, you must provide an empty struct
job, err := client.JobCreate(chunkify.JobCreateParams{
SourceId: source.Id,
Format: chunkify.JobCreateFormatParams{
WebmVp9: &chunkify.Vp9{},
},
})
The library provides paginated access to your jobs. Here's how to list jobs with filtering and pagination:
// Configure pagination and filtering parameters
params := chunkify.JobListParams{
Limit: chunkify.Int64(10),
Offset: chunkify.Int64(0),
Status: chunkify.String(chunkify.JobStatusCompleted),
}
// Get the first page of results
result, err := client.JobList(params)
if err != nil {
log.Fatal(err)
}
// Access the current page of jobs
for _, job := range result.Items {
fmt.Printf("Job ID: %s, Status: %s\n", job.Id, job.Status)
}
// Get the next page
nextPage, err := result.Next()
if err != nil {
// An error is returned if there is no next page available.
log.Fatal(err)
}
// Process next page...
By default, we choose automatically the right number of transcoder with the right CPU. If you want to customize this behavior, you can pass the options like this:
job, err := client.JobCreate(chunkify.JobCreateParams{
SourceId: source.Id,
Format: chunkify.JobCreateFormatParams{
Mp4H264: config,
},
Transcoder: &chunkify.JobCreateTranscoderParams{
Quantity: 10,
Type: chunkify.TranscoderType8vCPU,
},
})
The library client automatically tracks the available CPU resources from the API responses. You can access this information through the LastAvailableCpuCount
field:
// LastAvailableCpuCount will be -1 (CpuCountUnknown) until the first API response
if client.LastAvailableCpuCount == chunkify.CpuCountUnknown {
fmt.Println("CPU count not yet available")
} else {
fmt.Printf("Available CPUs: %d\n", client.LastAvailableCpuCount)
}
To ensure that webhook notifications are coming from Chunkify, you should verify the signature of each request. Here's an example showing how to do it:
// In your webhook handler
func handleWebhook(w http.ResponseWriter, r *http.Request) {
// Get the signature from the X-Chunkify-Signature header
signature := r.Header.Get("X-Chunkify-Signature")
// Read the request body
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Error reading request body", http.StatusBadRequest)
return
}
// Verify the signature using your signature key
if !chunkify.VerifyNotificationSignature(body, signature, "your_signature_key") {
http.Error(w, "Invalid signature", http.StatusUnauthorized)
return
}
// Parse the webhook payload
var payload chunkify.NotificationPayload
if err := json.Unmarshal(body, &payload); err != nil {
http.Error(w, "Error parsing webhook", http.StatusBadRequest)
return
}
fmt.Println("Received notification", payload.Id, payload.Event)
switch data := payload.Data.(type) {
case *chunkify.NotificationPayloadJobCompletedData:
fmt.Printf("Job %s completed with %d files\n", data.Job.Id, len(data.Files))
default:
fmt.Printf("unexpected payload data type: %T\n", data)
}
}
The library provides structured error handling with semantic error types and detailed API error information. You can handle errors gracefully:
client := chunkify.NewClient(chunkify.AccessTokens{
TeamToken: "sk_team_token",
ProjectToken: "sk_project_token",
})
source, err := client.SourceCreate(chunkify.SourceCreateParams{
Url: "http://somevideos.com/your_source.mp4",
})
if err != nil {
// Check if it's an API error and get detailed information
var apiError chunkify.ApiError
if errors.As(err, &apiError) {
fmt.Printf("API Error Type: %s\n", apiError.Type)
fmt.Printf("HTTP Status Code: %d\n", apiError.Code)
fmt.Printf("Error Message: %s\n", apiError.Message)
} else {
// Handle other types of errors (network, parsing, etc.)
fmt.Printf("Error: %v\n", err)
}
return
}
The library provides predefined error variables for semantic error checking:
ErrAuthentication
- Invalid API keyErrValidation
- Invalid input parametersErrNotFound
- Resource not foundErrTooManyRequests
- Rate limit exceededErrForbidden
- Permission deniedErrUnexpected
- Server errors
client := chunkify.NewClient(chunkify.AccessTokens{
TeamToken: "sk_team_token",
ProjectToken: "sk_project_token",
})
source, err := client.SourceCreate(chunkify.SourceCreateParams{
Url: "http://somevideos.com/your_source.mp4",
})
if err != nil {
if errors.Is(err, chunkify.ErrAuthentication) {
// Handle auth issues
fmt.Println("Authentication failed - check your API keys")
} else if errors.Is(err, chunkify.ErrValidation) {
// Handle validation issues
fmt.Println("Invalid parameters provided")
} else if errors.Is(err, chunkify.ErrTooManyRequests) {
// Implement retry logic
fmt.Println("Rate limited - please retry later")
} else {
// Handle other errors
fmt.Printf("Unexpected error: %v\n", err)
}
return
}