The next generation Cloud transcoding service.
The Chunkify CLI brings super-fast video transcoding to your terminal. With a single command, you can upload local files, transcode videos using Chunkify's parallel technology, and download the processed files to your local disk.
For local development, the Chunkify CLI provides a convenient command to forward webhook notifications to your local application URL.
Useful links:
- Prerequisites
- Installation
- Authentication
- Quick Start with Chunkify
- Transcoding Parameters
- JSON Output
- CLI Profiles
- Chunkify API Integration
You need to have a Chunkify account to use the CLI. If you don't have one, you can sign up for a free trial at chunkify.dev.
Installing the latest version:
curl -fsSL https://chunkify.dev/install.sh | bash
After the installation, the first step is to set your project token:
chunkify config token <sk_project_token>
Tip
You will find the project token in your project settings page under the Project access token section. It's best to create a new token for the CLI.
Another way to authenticate is to set the environment variable CHUNKIFY_TOKEN
:
export CHUNKIFY_TOKEN=sk_project_token
If you have multiple projects that you want to use with the CLI, simply use the --profile
flag to use a different project token. See CLI Profiles for more details.
You can use the Chunkify CLI to transcode a local video, a URL, or a source ID if it has already been uploaded to Chunkify.
chunkify -i video.mp4 -o video_1080p.mp4 -f mp4/h264 -s 1920x1080 --crf 21
It will upload the video to Chunkify, transcode it to MP4 H.264, and download it to your local disk.
By default, the number of transcoders and their type will be selected automatically according to the input and output specifications.
To define them yourself, use --transcoders
and --vcpu
like this:
chunkify -i video.mp4 \
-o video_720p.mp4 \
-f mp4/h264 \
-s 1280x720 \
--crf 24 \
--transcoders 10 \
--vcpu 8
Tip
When transcoding the same local video multiple times, we use the source already created on Chunkify so you won't need to upload the video more than once.
You can also transcode a video that is publicly available via HTTP:
chunkify -i https://cdn/video.mp4 -o video_1080p.mp4 -f mp4/h264 -s 1920x1080 --crf 21
If a video has already been uploaded to Chunkify, you can simply use the source ID as the input:
chunkify -i src_33aoGbF6fyY49qUVebIeNaxZJ34 \
-o video_av1_1080p.mp4 \
-f mp4/av1 \
-s 1920x1080 \
--crf 34 \
--preset 7
Tip
If --format
is omitted but --output
is set, we will match the file extension to the appropriate format:
.mp4
→mp4/h264
.webm
→webm/vp9
.m3u8
→hls/h264
.jpg
→jpg
Sometimes, it's better to know what the input specifications are before transcoding. Use --input
without setting --format
, and it will only upload or make available the source video:
chunkify -i chunkify-animation-logo.mp4
██ ▗▄▄▖▗▖ ▗▖▗▖ ▗▖▗▖ ▗▖▗▖ ▗▖▗▄▄▄▖▗▄▄▄▖▗▖ ▗▖
██ ▐▌ ▐▌▄▐▌▐▌ ▐▌▐▛▚▖▐▌▐▌▗▞▘ █ ▐▌▗▖ ▝▚▞▘
██ ▝▚▄▄▖▐▌ ▐▌▝▚▄▞▘▐▌ ▐▌▐▌ ▐▌▗▄█▄▖▐▌ ▐▌
Chunkify CLI version: dev
https://chunkify.dev
────────────────────────────────────────────────
▮ Source: chunkify-animation-logo.mp4
Duration: 00:03 Size: 61KB Video: h264, 400x400, 149KB/s, 24.00fps
────────────────────────────────────────────────
Source ID: src_33dLly8jh7bQxVJ5L9LeMG3FAVc
Now you can perfectly adapt your transcoding settings to your needs with a second command by either setting --input
to the source ID or the same local file (if uploaded from disk).
Chunkify supports 3 HLS formats: hls/h264
, hls/h265
, and hls/av1
.
Warning
Keyframes must be aligned for all renditions, so you must use the same values for --gop
, --x264keyint
(H.264), and --x265keyint
(H.265). For hls/av1
, only --gop
is necessary.
chunkify -i video.mp4 \
-o video_540p.m3u8 \
-f hls/h264 \
-s 540x0 \
-g 120 \
--x264keyint 120 \
--vb 800k \
--ab 128k
Once the video is transcoded, the CLI will return a summary including the HLS Manifest ID
, which we will use for the next command:
chunkify -i video.mp4 \
-o video_720p.m3u8 \
-f hls/h264 \
-s 720x0 \
-g 120 \
--x264keyint 120 \
--vb 1200k \
--ab 128k \
--hls-manifest-id hls_33atK0NkjF3lz6qUNi3GLwYdi0m
Note
The video bitrate and/or audio bitrate are mandatory for HLS output
Now we have 2 renditions that belong to the same manifest:
manifest.m3u8
video_540p.mp4
video_540p.m3u8
video_720p.mp4
video_720p.m3u8
To generate thumbnails every 10 seconds:
chunkify -i video.mp4 -o thumbnails.jpg -f jpg -s 320x0 --interval 10
If many thumbnails are required, it's recommended to generate a sprite image instead of multiple individual images. A sprite image is a single image containing many thumbnails arranged in a grid, which is more efficient when there are hundreds of them to download for displaying a preview.
chunkify -i video.mp4 -o sprite.jpg -f jpg -s 160x0 --interval 5 --sprite
Note
For all JPG outputs, an images.vtt
file is generated, which can be loaded by an HTML5 player to display a mini preview when hovering over the player progress bar
The VTT filename is always images.vtt
. Here is how it looks:
WEBVTT
00:00:00.000 --> 00:00:05.000
sprite-00000.jpg#xywh=0,0,160,160
00:00:05.000 --> 00:00:10.000
sprite-00000.jpg#xywh=160,0,160,160
00:00:10.000 --> 00:00:15.000
sprite-00000.jpg#xywh=320,0,160,160
Flag | Type | Description |
---|---|---|
-i, --input |
string | Input video to transcode. It can be a file, HTTP URL or source ID (src_*) |
-o, --output |
string | Output file path |
-f, --format |
string | mp4/h264 , mp4/h265 , mp4/av1 , webm/vp9 , hls/h264 , hls/h265 , hls/av1 , jpg |
--transcoders |
int | Number of transcoders to use |
--vcpu |
int | vCPU per transcoder (4, 8, or 16) |
Flag | Type | Description | Value |
---|---|---|---|
-s, --resolution |
string | Set resolution wxh | 0-8192x0-8192 |
-r, --framerate |
float | Set frame rate | 15-120 |
-g, --gop |
int | Set group of pictures size | 1-300 |
--vb |
int | Set video bitrate in bits per second | 100000-50000000. You can also use units like 2000K or 2M |
--maxrate |
string | Set maximum bitrate in bits per second | 100000-50000000. You can also use units like 2000K or 2M |
--bufsize |
string | Set buffer size in bits | 100000-50000000. You can also use units like 2000K or 2M |
--pixfmt |
string | Set pixel format | yuv410p, yuv411p, yuv420p, yuv422p, yuv440p, yuv444p, yuvJ411p, yuvJ420p, yuvJ422p, yuvJ440p, yuvJ444p, yuv420p10le, yuv422p10le, yuv440p10le, yuv444p10le, yuv420p12le, yuv422p12le, yuv440p12le, yuv444p12le, yuv420p10be, yuv422p10be, yuv440p10be, yuv444p10be, yuv420p12be, yuv422p12be, yuv444p12be |
--vn |
bool | Disable video |
Flag | Type | Description | Value |
---|---|---|---|
--ab |
int | Set audio bitrate in bits per second | 32000-512000. You can also use units like 128K |
--channels |
int | Set number of audio channels | 1, 2, 5, 7 |
--an |
bool | Disable audio |
Flag | Type | Description | Value |
---|---|---|---|
--crf |
int | Set constant rate factor | H.264/H.265: 16-35, AV1: 16-63, VP9: 15-35 |
--preset |
string | Set encoding preset | H.264/H.265: ultrafast, superfast, veryfast, faster, fast, medium, AV1: 6-13 |
--profilev |
string | Set video profile | H.264: baseline, main, high, high10, high422, high444, H.265/AV1: main, main10, mainstillpicture |
--level |
int | Set encoding level | H.264: 10, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51, H.265: 30, 31, 41, AV1: 30, 31, 41 |
--x264keyint |
int | H.264 - Set x264 keyframe interval | 1-300 |
--x265keyint |
int | H.265 - Set x265 keyframe interval | 1-300 |
Flag | Type | Description | Value |
---|---|---|---|
--quality |
string | Set VP9 quality | good, best, realtime |
--cpu-used |
string | Set VP9 CPU usage | 0-8 |
Flag | Type | Description | Value |
---|---|---|---|
--hls-manifest-id |
string | Set HLS manifest ID | |
--hls-time |
int | Set HLS segment duration in seconds | 1-10 |
--hls-segment-type |
string | Set HLS segment type | mpegts, fmp4 |
--hls-enc |
bool | Enable HLS encryption | |
--hls-enc-key |
string | Set HLS encryption key | |
--hls-enc-key-url |
string | Set HLS encryption key URL | |
--hls-enc-iv |
string | Set HLS encryption IV |
Flag | Type | Description | Value |
---|---|---|---|
--interval |
int | Set frame extraction interval in seconds | 1-60 |
--sprite |
bool | Generate sprite sheet instead of multiple JPG files |
It's possible to output the progress in JSON format by passing the --json
flag.
chunkify -i video.mp4 -o video_1080p.mp4 -s 1920x1080 --crf 21 --json
{"status":"Queued","progress":0,"fps":0,"speed":"0.0x","out_time":0,"eta":""}
{"status":"Queued","progress":0,"fps":0,"speed":"0.0x","out_time":3,"eta":""}
{"status":"Ingesting","progress":20,"fps":0,"speed":"0.0x","out_time":3,"eta":""}
{"status":"Transcoding","progress":40,"fps":100,"speed":"5x","out_time":3,"eta":""}
{"status":"Transcoding","progress":70,"fps":100,"speed":"5x","out_time":3,"eta":""}
{"status":"Merging","progress":90,"fps":12,"speed":"1.2x","out_time":3,"eta":""}
{"status":"Merging","progress":100,"fps":12,"speed":"1.2x","out_time":3,"eta":""}
{"status":"Downloading","progress":100,"fps":0,"speed":"105MB/s","out_time":0,"eta":"0s"}
{"status":"Completed","progress":0,"fps":0,"speed":"","out_time":0,"eta":""}
You may have multiple projects and want to use different project tokens for different tasks, or simply to differentiate between different environments.
The CLI provides a global --profile
flag to use different project tokens.
First, let's save a new token for the testing
profile:
chunkify config token sk_project_token --profile testing
Now you can use this profile with the --profile
flag for transcoding:
chunkify -i video.mp4 -o video_1080p.mp4 -f mp4/h264 -s 1920x1080 --crf 21 --profile testing
Note
If no profile given, the CLI will use the default one
When integrating Chunkify into your app, you must rely on webhooks to receive events when a job is completed or when an upload is created. We have added the listen
command to forward webhooks to your local server URL, which is normally not available publicly.
Note
First, you need to retrieve your webhook secret in your project settings page under the Webhooks section.
Start forwarding webhooks to your local server:
chunkify listen \
--forward-to http://localhost:3000/webhooks/chunkify \
--webhook-secret <secret-key>
██ ▗▄▄▖▗▖ ▗▖▗▖ ▗▖▗▖ ▗▖▗▖ ▗▖▗▄▄▄▖▗▄▄▄▖▗▖ ▗▖
██ ▐▌ ▐▌▄▐▌▐▌ ▐▌▐▛▚▖▐▌▐▌▗▞▘ █ ▐▌▗▖ ▝▚▞▘
██ ▝▚▄▄▖▐▌ ▐▌▝▚▄▞▘▐▌ ▐▌▐▌ ▐▌▗▄█▄▖▐▌ ▐▌
Chunkify CLI version: dev
https://chunkify.dev
────────────────────────────────────────────────
[mac.home] Start forwarding to http://localhost:3000/webhooks/chunkify
Events:
- job.completed
- job.failed
- job.cancelled
- upload.completed
- upload.failed
- upload.expired
────────────────────────────────────────────────
[200 OK] notf_33f3pVlO3782tPF9CkioGK1IKTu job.completed (job_33f3ocg9Vg0o0gDgg5JpCCR3DzX)
[200 OK] notf_33f3tiGWDw78SLHefdswGaL7UpB job.completed (job_33f3siy9JhMrlsIY69q2gHqL3bh)
By default, it will forward all events, but you can specify the ones you are interested in:
chunkify listen \
--forward-to http://localhost:3000/webhooks/chunkify \
--webhook-secret <secret-key> \
--events job.completed,job.failed,job.cancelled
What chunkify listen
does under the hood:
- Creates a temporary webhook in your project
- Forwards all notifications to your local server
- Signs requests with the webhook secret key
- Cleans up the webhook when you exit
- Go 1.x or higher
Contributions are welcome! Please feel free to submit a Pull Request.
MIT