Video processing

Uploadcare can encode video files from all popular formats to MP4, WEBM, or OGG, adjust their quality, dimensions, cut out a video fragment, and generate thumbnails via REST API.

Additionally, once any video file is uploaded, we extract its metadata (duration, format, bitrate, and specific audio & video stream metadata: codec, bitrate, frame rate, and dimensions). It becomes available under the video_info key of the file information object. The file information can be retrieved by requesting to the REST API v0.6 or higher.

How it works

Video processing works asynchronously through the REST API, unlike the image processing operations performed on the fly.

It generates encoded output as a separate file while the original file remains intact.

  1. Start a processing job via REST API. Send an input file UUID with necessary processing operations.
  2. Wait until the processing job status becomes finished.
  3. The processed file can be addressed via its new UUID, as well as an URL with operations provided in a processing request.

Every video operation produces at least 2 files (even if it hasn't been requested explicitly):

  • Transcoded video
  • A thumbnail

Processing job

The endpoint for your requests is:

https://api.uploadcare.com/convert/video/
curl -X POST \
    -H "Content-Type: application/json" \
    -H "Accept: application/vnd.uploadcare-v0.7+json" \
    -H "Authorization: Uploadcare.Simple $YOUR_PUBLIC_KEY:$YOUR_SECRET_KEY" \
    -d '{"paths": ["$UUID/video/-/format/ogg/"], "store": "1"}' \
    "https://api.uploadcare.com/convert/video/"

Project pointed with $YOUR_PUBLIC_KEY and $YOUR_SECRET_KEY should have enabled Video processing feature. The $UUID of the source file to convert should belong to the project.

Input file identifiers should be formatted with UUID followed be /video/ (please note, this is not operation, so there shouldn't be /-/ between them) and ended by operations separated by /-/:

/:uuid/video/-/:operation/:parameters/-/:operation/:parameters/

Operations can be omitted; the video will then be delivered as mp4 with its quality is set to normal.

Check out detailed API reference for POST /convert/video/.

Webhook event

To get the job result, you need to enable file.uploaded in the Webhook section of the dashboard.

After completing the processing job, the webhook will be sent to the endpoint you specified in the webhook settings.

File information in response:

"initiator": {
      "type": "addon",
      "detail": {
          "addon_name": "zencoder_convert_video",
          "request_id": ":request_id",
          "source_file_uuid": ":UUID"
      }
   }
   "hook": {
    ...
    "event": "file.uploaded",
    "is_active": true,
    "version": "0.7",
    "created_at": "2023-10-26T09:32:40.114516Z",
    "updated_at": "2023-10-26T09:32:40.114516Z"
},
"data": {
    "content_info": {
        "video": {
            "duration": 5769,
            "format": "mpeg4",
            "bitrate": 1778,
            "audio": [{
                "bitrate": 87,
                "codec": "aac",
                "sample_rate": 44100,
                "channels": 2
            }],
            "video": [{
                "height": 248,
                "width": 440,
                "frame_rate": 30,
                "bitrate": 1691,
                "codec": "h264"
            }]
        }
    }
}

After receiving source_file_uuid, you can make a GET request for the original file and get all the variations from there, including the thumbnail:

"uuid": ":UUID", "variations": {
    "video/-/format/mp4/-/quality/normal/-/size/440x380/": ":UUID_1",
    "video/-/format/mp4/-/quality/normal/-/size/512x384/": ":UUID_2",
    "video/-/format/mp4/-/quality/normal/-/size/440x380/-/thumbs~1/0/": ":UUID_1_thumbs",
    "video/-/format/mp4/-/quality/normal/-/size/512x384/-/thumbs~1/0/": ":UUID_2_thumbs"
}

Job status

If your application does not have a backend or uses a mobile version, you can submit the request yourself.

As a request result, you immediately receive an UUID of the new file. But it can be not accessible due to that conversion takes time. Once you get a processing job result, you can get a processing job status using :token.

curl -X GET \
    -H "Content-Type: application/json" \
    -H "Accept: application/vnd.uploadcare-v0.7+json" \
    -H "Authorization: Uploadcare.Simple $YOUR_PUBLIC_KEY:$YOUR_SECRET_KEY" \
    "https://api.uploadcare.com/convert/video/status/:token/"

Check out detailed API reference for GET /convert/video/status/{token}/.

Job result

The processed video becomes addressable via both a new UUID and a CDN URL you provided in the request:

https://ucarecdn.com/:new_uuid/
https://ucarecdn.com/:original_uuid/video/-/:operation/:parameters/

Applying the same set of conversion operations to the original video will create a new file with a different :new_uuid, the conversion result will be the same.

List of video operations

You can change your video canvas size, quality, format, and length by applying video transform operations. This way, you can optimize video and find a perfect balance between the desired video quality, loading time, and traffic usage.

Size

-/size/:one_or_two_dimensions/
-/size/:one_or_two_dimensions/:resize_mode/

Downscales a video to the specified dimensions. If the video is smaller, it does nothing.

  • :one_or_two_dimensions — width and height in pixels separated by x, one of the values can be omitted.
    The value you specify for any dimensions should be a non-zero integer divisible by 4.
    Examples: 720x540, 720x, x540.
  • :resize_mode — presets that control aspect ratio and cropping behavior:
    • preserve_ratio (default) — preserve the aspect ratio of the original file.
    • change_ratio — matches the output video to provided dimensions, no matter the original aspect ratio.
    • scale_crop — matches the output video to provided dimensions and crops the rest of the pixels along with one ax (top/bottom or left/right).
    • add_padding — letterbox the video to exactly match the output frame size (add black bars).

If you explicitly specify a non-default :resize_mode, the missing dimension size will be taken from the original file. For instance, -/size/x600/change_ratio/ for a 640x480 original frame size will output your video as 640x600.

Here are some examples:

/:uuid/video/-/size/720x540/
/:uuid/video/-/size/800x600/change_ratio/
/:uuid/video/-/size/512x384/scale_crop/
/:uuid/video/-/size/512x384/add_padding/
/:uuid/video/-/size/720x/
/:uuid/video/-/size/x540/

Quality

-/quality/:value/

Sets the video quality level that affects the file size. In turn, it affects loading time and user-generated traffic.

  • :value — one of the following values:
    • normal (default) — suits most cases.
    • better — better video quality, larger file size compared to normal.
    • best — useful when you want perfect quality and don't care about the file size. It's larger than better.
    • lighter — saves traffic without a significant subjective quality loss, smaller file size compared to normal.
    • lightest — lowest visual quality that provides a minimal loading time, smaller than lighter.

Format

-/format/:format/

Converts a file to one of the web video formats.

  • :format — one of the following values:
    • mp4 (default) — MPEG-4 is widely supported across devices and browsers. Videos encoded with mp4 are compressed via H.264 codec and will work on Android and iOS, in Safari, Chrome, and EDGE. Choose it when you want to go universal or in case you need a fallback.
    • webm — WebM is an open media file format designed for the web. Video streams are compressed via VP8 or VP9 video codec. Audio gets compressed with Vorbis or Opus, more. WebM is compatible with many of the current devices and browsers and backed by Google.
    • ogg — Ogg/Theora is a free and open video compression format from Xiph.org. Theora is considered competitive at low bitrates, making it suitable for the web, more. Theora is backed by the community and supported by fewer browsers than webm.

Cut

-/cut/:start_time/:length/

Cuts out a video fragment based on the following parameters:

  • :start_time — defines the starting point of a fragment to cut based on your input file timeline.
  • :length — defines the duration of that fragment.

Both of the parameters can be formatted in one of the following ways:

  • HHH:MM:SS.sss — consists of the following parameters:
    • HHH — hours ranging from 0 to 999, can be omitted.
    • MM — minutes ranging from 0 to 59, can be omitted.
    • SS — second ranging from 0 to 59.
    • sss — fractional part of a second ranging from 0 to 999, сan be omitted.
  • SSSS.sss — consists of the following parameters:
    • SSSS — second ranging from 0 to 9999999.
    • sss — fractional part of a second ranging from 0 to 999, сan be omitted.

You can also set :length to end keyword and your video fragment will include all the duration of your input starting at :start_time.

Note that :start_time and :length may not be exact depending on how keyframes are arranged within your input video.

Here are some examples:

/:uuid/video/-/cut/1:2:40.535/2:20.0/
/:uuid/video/-/cut/001:02:40.535/02:20.0/
/:uuid/video/-/cut/2:30.535/2:20.0/
/:uuid/video/-/cut/1:2:40.535/end/
/:uuid/video/-/cut/3760.535/140/
/:uuid/video/-/cut/3760.535/end/

Video thumbnails

Note, thumbs should be put last in your sequence of operations in a processing job URL.

Generating thumbnails

-/thumbs~N/

When specified in the processing request, it'll create N thumbnails for your video, where N is a non-zero integer ranging from 1 to 50; defaults to 1.

If the operation is omitted, a single thumbnail gets generated from the middle frame of your video. If you define another N, thumbnails are generated from the frames evenly distributed along your video timeline. For example, if you have a 20-second video with N set to 20, it'll generate a thumbnail every second of your video.

Whenever thumbnails should be generated from the beginning of the video, it is set by an extra argument to thumbs~N operation:

  • yes for generating from the start of the video.
  • no (default) - from the middle.

cdn›-/thumbs~1/yes/ - will generate a single thumbnail from first frame.

Requesting thumbnails

In an API response, you get a thumbnails_group_uuid. It is a collection of image files stored as a file group. You can access individual images and apply image processing operations. There also is a way to request thumbnails.

/:uuid/video/-/:operations/-/thumbs~20/:number/

Where :uuid and :operations are your video file identifier and processing operations passed in a processing job request.

  • :number is a zero-based index of a particular thumbnail in a created set. In the example above, the :number ranges from 0 to 19.

You can also go with:

/:uuid/video/-/:operations/-/thumb/

Which is a shortcut for:

/:uuid/video/-/:operations/-/thumbs~1/0/

If you omit a thumbnail index, we return the first thumbnail from your set. In the following example, the first thumbnail from 20 is returned:

/:uuid/video/-/:operations/-/thumbs~20/

API integrations

You don't have to code most of the low-level API integrations. We have high-level libraries for all popular platforms:

Billing

  • This feature is available on paid plans.
  • This operation uploads a new file.
  • Learn how we charge for this operation.

Examples

In our billing model we charge 100 operations per minute of the output video.

Converting a 10-minute video to mp4 will cost 10 * 100 = 1000 ops.

If you cut out the first minute out of the video, the cost is 100 ops (or 1 minute) because the output video's length is goint to be 1 minute.