Upload videos

 

Cloudinary is a cloud-based service that provides an end-to-end media management solution for images and videos, including upload, storage, administration, manipulation, optimization and delivery.

With Cloudinary you can easily upload videos to the cloud and automatically perform smart video manipulations without installing any complex software. Cloudinary provides a secure and comprehensive API for easily uploading videos from server-side code, directly from the browser or from a mobile app. You can either use Cloudinary's upload API directly or through one of Cloudinary's client libraries (SDKs), which wrap the upload API and simplify integration with web sites and mobile applications.

The uploaded videos can then be automatically converted to all relevant formats suitable for web viewing, optimized for web browsers and mobile devices, normalized, manipulated in real time, and delivered through a fast CDN to users (see the Video manipulation and delivery documentation for more information).

While uploading videos you can also apply transformations (e.g. changing dimensions or format) and assign tags to them, and you can manage all uploaded videos using Cloudinary's Management Console and API.

Audio files (such as MP3s) can also be uploaded as a video resource.

You can also upload videos from remote locations using the auto-upload functionality.

Cloudinary’s video management service enables video upload as follows:

Uploading from server-side code

You can use the API directly within your custom code (as explained on the Upload Images page), but it is simpler and recommended to use Cloudinary's SDKs. Uploading is done over HTTPS using a secure protocol based on your account's cloud_name, api_key and api_secret parameters. Cloudinary can automatically detect the type of resource uploaded by setting the resource_type parameter to auto, or you can set the parameter to video if you know in advance that it's a video file. The file parameter can be a local file path, the actual data of a file, the Data URI (base-64 encoded) a remote HTTP URL of an existing file, or an S3 URL (of a whitelisted bucket).

The process of server-side uploading for video is the same as that for images. For additional details, see Remote upload or the relevant framework integration documentation: Ruby on Rails, PHP, Django, Node.js, Java or .NET.

By default, uploading is performed synchronously, and once finished, the uploaded video is immediately available for manipulation and delivery.

Use the following syntax to upload a video:

Ruby:
Cloudinary::Uploader.upload(file, 
            :resource_type => :video,
            : <optional_parameters...>)
PHP:
\Cloudinary\Uploader::upload(file, 
        array("resource_type" => "video", 
              "<optional_parameters...>"));
Python:
cloudinary.uploader.upload(file, 
        resource_type = "video", 
        <optional_parameters...>)
Node.js:
cloudinary.v2.uploader.upload(file, 
        { resource_type: "video", 
          <optional_parameters...> },
        function(result) {console.log(result); });
Java:
cloudinary.uploader().upload(file, 
        ObjectUtils.asMap("resource_type", "video", 
                          "<optional_parameters...>"));
.Net:
public VideoUploadResult Upload(VideoUploadParams parameters);
Endpoint:
https://api.cloudinary.com/v1_1/<cloud_name>/video/upload

Note: This method will only upload files up to 100 MB in size. To upload larger files, use the chunked video upload method.

For example, uploading a local video file named dog.mp4:

Ruby:
Cloudinary::Uploader.upload("dog.mp4", :resource_type => :video)
PHP:
\Cloudinary\Uploader::upload("dog.mp4", 
            array("resource_type" => "video"));
Python:
cloudinary.uploader.upload("dog.mp4", 
        resource_type = "video")
Node.js:
cloudinary.v2.uploader.upload("dog.mp4", 
        { resource_type: "video" },
        function(result) {console.log(result); });
Java:
cloudinary.uploader().upload("dog.mp4", 
        ObjectUtils.asMap("resource_type", "video"));
.Net:
var uploadParams = new VideoUploadParams()
{
  File = new FileDescription(@"dog.mp4"),
  ResourceType = "video"  
};
var uploadResult = cloudinary.Upload(uploadParams);

Video upload parameters

For a full list of the upload method parameters, see the Upload method in the Upload API Reference.

Video upload response

An upload API call returns a response that includes the HTTP and HTTPS URLs for accessing the uploaded video, as well as additional information regarding the uploaded video: The Public ID of the video (used in the Media Library, Admin API, and for building manipulation and delivery URLs), the video's dimensions, and duration, the video format and file size in bytes, a signature for verifying the response, various technical audio and video parameters such as codec and bit-rate, and more. The following is an example of the JSON response returned:

{
  "public_id": "ygzxwxmflekucvqcrb8c",
  "version": 1427018743,
  "signature": "4618ba7c3461b6531cb9d2f16b06ce672af793b6",
  "width": 854,
  "height": 480,
  "format": "mp4",
  "resource_type": "video",
  "created_at": "2017-03-22T10:05:43Z",
  "tags": [  ],
  "bytes": 9094354,
  "type": "upload",
  "etag": "7e3977ca45a2c2a063e4f29fa3ecdfdd",
  "url": "http://res.cloudinary.com/demo/video/upload/v1427018743/ygzxwxmflekucvqcrb8c.mp4",
  "secure_url": "https://res.cloudinary.com/demo/video/upload/v1427018743/ygzxwxmflekucvqcrb8c.mp4",
  "audio": {
    "codec": "aac",
    "bit_rate": "246679",
    "frequency": 48000,
    "channels": 2,
    "channel_layout": "stereo"
  },
  "video": {
    "pix_format": "yuv420p",
    "codec": "h264",
    "level": 31,
    "bit_rate": "5170819"
  },
  "frame_rate": 29.97002997002997,
  "bit_rate": 5424041,
  "duration": 13.4134
}

Uploading audio

Audio files are treated as video files without a visual element and thus are uploaded in the same way as videos, using video as the resource_type. For example, uploading a local audio file named audio_sample.mp3:

Ruby:
Cloudinary::Uploader.upload("audio_sample.mp3", :resource_type => :video)
PHP:
\Cloudinary\Uploader::upload("audio_sample.mp3", 
            array("resource_type" => "video"));
Python:
cloudinary.uploader.upload("audio_sample.mp3", 
        resource_type = "video")
Node.js:
cloudinary.uploader.upload("audio_sample.mp3", 
        { resource_type: "video" }
        function(result) {console.log(result); });
Java:
cloudinary.uploader().upload("audio_sample.mp3", 
        ObjectUtils.asMap("resource_type", "video"));

Direct uploading from the browser

Uploading directly from the browser is enabled by Cloudinary's jQuery plugin. This is identical to setting up client side image uploading: the same upload field can be used for uploading any media file type. For more information on direct uploading environment setup see Ruby on Rails, PHP, Django, Node.js, Java, .NET, or jQuery and the blog post on Direct upload made easy, from browser or mobile app to the cloud

Activate client side video uploading by embedding an upload input field in your HTML pages with the cl_upload_tag method. The method adds a file input field to your form, and selecting or dragging a file to this input field will automatically initiate uploading from the browser to Cloudinary. For example, using Ruby on Rails (other frameworks use a similar concept):

cl_upload_tag(:video_id, options = {})

When uploading is completed, the identifier of the uploaded video is set as the value of the given input field in your HTML page (e.g., video_id in the example above). You can then process the identifier received by your controller and store it for future use, exactly as if you're using a standard server side uploading.

Upload parameters for direct upload

When uploading directly from the browser using a signed upload, you can use the same set of options available for server-side uploading.

For the full list, see the Upload method in the Upload API Reference.

Note: For security reasons, only this limited set of parameters can be used in an unsigned upload request.

Chunked video upload

A better method to upload large files, which offers a degree of tolerance for network issues, is the upload_large API call. The method uploads a large video to the cloud in separate chunks.

Note: This method must be used to upload files larger than 100 MB in size.

Ruby:
Cloudinary::Uploader.upload_large(file, 
        :resource_type => :video, options = {})
PHP:
\Cloudinary\Uploader::upload_large(file, 
        array("resource_type" => "video"));
Python:
cloudinary.uploader.upload_large(file, 
        resource_type = "video")
Node.js:
cloudinary.uploader.upload_large(file, 
            function(result) {console.log(result); }, 
            { resource_type: "video" });
Java:
cloudinary.uploader().upload_large(file, 
            ObjectUtils.asMap("resource_type", "video"));

For example, uploading a large video file named my_large_video.mp4:

Ruby:
Cloudinary::Uploader.upload_large("my_large_video.mp4", 
        :resource_type => :video)
PHP:
\Cloudinary\Uploader::upload_large("my_large_video.mp4", 
        array("resource_type" => "video"));
Python:
cloudinary.uploader.upload_large("my_large_video.mp4", 
        resource_type = "video")
Node.js:
cloudinary.uploader.upload_large("my_large_video.mp4", 
        function(result) {console.log(result); }, 
        { resource_type: "video" });
Java:
cloudinary.uploader().upload_large("my_large_video.mp4",
            ObjectUtils.asMap("resource_type", "video"));

By default, chunk size defaults to 20 Megabytes but can be set to any value between 5 MB and 100 MB by using the chunk_size parameter. For example, uploading a large video file named my_large_video.mp4 and setting chunk size to 6 MB:

Ruby:
Cloudinary::Uploader.upload_large("my_large_video.mp4",
            :resource_type => :video, :chunk_size => 6_000_000)
PHP:
\Cloudinary\Uploader::upload_large("my_large_video.mp4", 
        array("resource_type" => "video", 
        "chunk_size" => 6000000));
Python:
cloudinary.uploader.upload_large("my_large_video.mp4", 
        resource_type = "video", chunk_size = 6000000)
Node.js:
cloudinary.uploader.upload_large("my_large_video.mp4", 
        function(result) {console.log(result); }, 
        { resource_type: "video", chunk_size: 6000000 });
Java:
cloudinary.uploader().upload_large("my_large_video.mp4",
            ObjectUtils.asMap("resource_type", "video"
            "chunk_size", 6000000));

For direct uploading from the browser, the following method adds a file input field that performs uploading from the browser using jQuery.

cl_upload_tag(:video_id, :chunk_size => 6_000_000)

When uploading is completed, the identifier of the uploaded video is set as the given value of the input field in your HTML page (e.g., video_id in the example above). You can then process the identifier received by your controller and store it for future use, exactly as if you're using standard server side uploading.

Note: The upload_large method is supported only in the Cloudinary SDKs. When directly calling the API, you can make use of the byte Content-Range entity-header HTTP specification to send the file in multiple calls.

Eager video transformations

Cloudinary can manipulate your videos on demand, on-the-fly, when accessed by your visitors (lazy transformations), or during the video upload process (eager transformations).

For lazy transformations, all transformed videos are generated on-the-fly, stored persistently, cached and delivered through a fast CDN. The time required for generating a transformation depends on various factors: original video dimensions, video file size, requested dimensions, applied effects and specific transformations, although videos start streaming immediately while being manipulated.

The eager approach requires a little planning, but is highly recommended if you have to make sure that all transformed videos are ready for fast delivery even for the first visitors to your videos. In this case, you can eagerly create the required transformations during the upload process so all transformed videos will already be available before your users access them for the first time. You also have the option to generate the eager transformations asynchronously in the background after the file is finished uploading, and then receive a callback notification to an HTTP URL you provide.

The upload API of Cloudinary supports additional optional parameters for eagerly transforming videos as follows:

  • eager - A list of transformations to create for the uploaded video during the upload process, instead of lazily creating them when first accessed by your site's visitors (see the Video manipulation reference documentation for more details on possible values). This option accepts either a hash of transformation parameters or an array of transformations.
  • eager_async - A Boolean value determining whether to generate the eager transformations asynchronously in the background after the file is finished uploading or online as part of the upload call. Default: false.
  • notification_url - An HTTP URL to notify your application (a webhook) when the file has completed uploading.
  • eager_notification_url - An HTTP URL to notify your application (a webhook) when the generation of eager transformations is completed.

Note: Online transformations are limited to files smaller than 40MB by default. Eager asynchronous transformations are required for larger files, and you need to use the eager_async parameter when uploading the file to specify any desired transformations. Users of paid plans can contact Cloudinary to raise this limit if needed.

For example, the following method will upload the dog.mp4 video and then generate two transformed videos as follows:

  1. Pad to a width and height of 300 pixels with a blue background, remove audio, normalize and optimize the video for web delivery.
  2. Crop to a width of 160 pixels and a height of 100 pixels with south gravity, remove audio, normalize and optimize the video for web delivery.

Furthermore, the transformations are to be done asynchronously after the video file finishes uploading, with a callback URL to notify your application once the transformations are complete:

Ruby:
Cloudinary::Uploader.upload("dog.mp4", :resource_type => :video,
            :eager => [
            {:width => 300, :height => 300, 
             :crop => :pad, :audio_codec => :none}, 
            {:width => 160, :height => 100, 
             :crop => :crop, :gravity => :south,
             :audio_codec => :none }], 
        :eager_async => true, 
        :eager_notification_url => "http://mysite/notify_endpoint")
PHP:
\Cloudinary\Uploader::upload("dog.mp4", array(
            "resource_type" => "video", 
            "eager" => array(
              array("width" => 300, "height" => 300,
                  "crop" => "pad", "audio_codec" => "none"),
              array("width" => 160, "height" => 100,
                  "crop" => "crop", "gravity" => "south",
                  "audio_codec" => "none")),
            "eager_async" => true,
            "eager_notification_url" => "http://mysite/notify_endpoint"
            ));
Python:
cloudinary.uploader.upload("dog.mp4", resource_type = "video",
            eager = [
              {"width": 300, "height": 300,
                  "crop": "pad", "audio_codec": "none"},
              {"width": 160, "height": 100,
                  "crop": "crop", "gravity": "south",
                  "audio_codec": "none"}],
            eager_async = true,
            eager_notification_url = "http://mysite/notify_endpoint")
Node.js:
cloudinary.uploader.upload("dog.mp4", 
        function(result) {console.log(result); }, 
        { resource_type: "video", 
        eager: [
            { width: 300, height: 300,
              crop: "pad", audio_codec: "none" }, 
          { width: 160, height: 100,
                  crop: "crop", gravity: "south",
                  audio_codec: "none" } ],                                   
        eager_async: true,
            eager_notification_url: "http://mysite/notify_endpoint"     });
Java:
cloudinary.uploader().upload("dog.mp4", 
        ObjectUtils.asMap("resource_type", "video",
        "eager", Arrays.asList(
              new Transformation().width(300).height(300).crop("pad").audioCodec("none"),
              new Transformation().width(160).height(100).crop("crop").gravity("south").audioCodec("none")),
            "eager_async", true,
            "eager_notification_url", "http://mysite/notify_endpoint"));

It is also possible to generate transformations for videos that have already been uploaded. This can be done with the explicit API method. This is particularly useful when Strict Transformations are enabled for your account and you cannot create transformed videos on the fly. It is also relevant when you need to transform large videos that exceed the limit of online video processing. The explicit method accepts similar parameters to the upload method parameters, except that the first parameter is the public ID of the video instead of the file itself.

For example, the following method will generate two transformations for the already uploaded video named dog:

  1. Scale to a width of 200 pixels, normalize and optimize the video for web delivery.
  2. Crop to a width of 360 pixels and a height of 200 pixels with north gravity, remove audio, normalize and optimize the video for web delivery.
Ruby:
Cloudinary::Uploader.explicit("dog", :resource_type => :video,
            :type => :upload, :eager => [
            {:width => 200, :crop => :scale}, 
            {:width => 360, :height => 200, 
             :crop => :crop, :gravity => :north,
             :audio_codec => :none }])
PHP:
\Cloudinary\Uploader::explicit("dog", array(
            "resource_type" => "video", "type" => "upload"
            "eager" => array(
              array("width" => 200, "crop" => "scale"),
              array("width" => 360, "height" => 200,
                  "crop" => "crop", "gravity" => "north",
                  "audio_codec" => "none"))));
Python:
cloudinary.uploader.explicit("dog", resource_type = "video",
            type = "upload", eager = [
              {"width": 200, "crop": "scale"},
              {"width": 360, "height": 200,
                  "crop": "crop", "gravity": "north",
                  "audio_codec": "none"}])
Node.js:
cloudinary.uploader.explicit("dog", 
        function(result) {console.log(result); }, 
        { resource_type: "video", type: "upload",
        eager: [
            { width: 200, crop: "scale" }, 
          { width: 360, height: 200,
                  crop: "crop", gravity: "north",
                  audio_codec: "none" } ] } );
Java:
cloudinary.uploader().explicit("dog", ObjectUtils.asMap(
            "resource_type", "video", "type", "upload", 
            "eager", Arrays.asList(
              new Transformation().width(200).crop("scale"),
              new Transformation().width(360).height(200).crop("crop").gravity("north").audioCodec("none"))));

Incoming transformations

Videos uploaded to Cloudinary are stored in the cloud as-is, by default. Once safely stored in the cloud, you can generate derived videos from these originals by asking Cloudinary to apply transformations and manipulations.

Sometimes you may want to normalize and transform the original videos before storing them in the cloud, by applying an incoming transformation as part of the upload request. Any video transformation parameter can be specified as an option in the upload call and these transformations are applied before saving the video in the cloud.

For example, to limit the dimensions of an uploaded video to a width of 300 pixels and a height of 200 pixels:

Ruby:
Cloudinary::Uploader.upload("my_video.mp4", 
            :resource_type => :video, :width => 300, 
            :height => 200, :crop => :limit)
PHP:
\Cloudinary\Uploader::upload("my_video.mp4", 
            array("resource_type" => "video", "width" => 300,
            "height" => 200, "crop" => "limit"));
Python:
cloudinary.uploader.upload("my_video.mp4", 
            resource_type = "video", "width" = 300, 
            "height" = 200, "crop" = "limit")
Node.js:
cloudinary.uploader.upload("my_video.mp4",
            function(result) { console.log(result); },
            { resource_type: "video", width: 300, 
            height: 200, crop: "limit" });
Java:
cloudinary.uploader().upload("my_video.mp4",
            ObjectUtils.asMap("resource_type", "video",
            "transformation", new Transformation().width(300).height(200).crop("limit")));

Upload presets

Cloudinary's Upload Presets feature is used for centrally controlling video upload options by defining a group of actions to be applied when uploading a video. Upload Presets include one or more upload parameters, and any of Cloudinary's upload parameters can be defined and included in a preset.

Each upload preset has a unique name. To apply an upload preset when uploading an video, simply specify this name as the value of the upload_preset parameter.

For example, uploading the video 'dog.mp4' and specifying an upload preset named 'splice':

Ruby:
Cloudinary::Uploader.upload("dog.mp4", 
            :resource_type => :video, :upload_preset => "splice")
PHP:
\Cloudinary\Uploader::upload("dog.mp4", 
            array("resource_type" => "video", 
            "upload_preset" => "splice"));
Python:
cloudinary.uploader.upload("dog.mp4", 
            resource_type = "video", upload_preset = 'splice')
Node.js:
cloudinary.uploader.upload("dog.mp4", function(result) { 
            console.log(result) }, { resource_type: "video", 
            upload_preset: "splice" });
Java:
cloudinary.uploader().upload(new File("dog.mp4"),
            ObjectUtils.asMap("resource_type", "video", 
            "upload_preset", "splice"));

For more information on upload presets, see Upload Presets and this post.

Video administration

Videos can be administered through Cloudinary's API and the Management Console which allow you to perform the following actions on an uploaded video file:

  • Delete the video.
  • Rename the video by changing its' public ID.
  • Manage the Tags assigned to the video (add, remove, replace).

The Cloudinary API also has useful methods for organizing your video files, such as listing all uploaded videos, listing tags, finding all videos that share a given tag, updating transformations, etc. See the documentation on the Cloudinary API for more information.

Deleting videos

Deleted videos are immediately and permanently deleted from your cloud storage. However, videos and transformed videos already downloaded by visitors to your web site might still be accessible for a few more days through cached copies on the CDN (using cache invalidation will cut this time down to up to one hour). Cloudinary's client libraries wrap the API and simplify the deleting with the destroy method. For example, deleting a video with the public ID of "dog":

Ruby:
Cloudinary::Uploader.destroy('dog', 
            :resource_type => :video)
PHP:
\Cloudinary\Uploader::destroy('dog', 
            array("resource_type" => "video"));
Python:
cloudinary.uploader.destroy('dog', 
            resource_type = "video")
Node.js:
cloudinary.uploader.destroy('dog', function(result) {
            console.log(result) }, { resource_type: "video" });
Java:
cloudinary.uploader().destroy("dog",
            ObjectUtils.asMap("resource_type", "video"));

You can also delete videos uploaded to Cloudinary by sending an HTTPS POST request to the following URL (replace 'demo' with your cloud name):

https://api.cloudinary.com/v1_1/demo/video/destroy

Required parameters:

  • public_id - The identifier of the uploaded video.
  • api_key - Your unique Cloudinary API Key.
  • timestamp - Unix time in seconds of the current time.
  • signature - A signature of all request parameters, based on your Cloudinary API Secret. See Creating API authentication signatures for more details.

Renaming videos

Renamed videos are immediately and permanently updated in your cloud storage and existing URLs of videos and associated derived videos are modified, while videos and transformed videos already downloaded by visitors of your web site might still be accessible for a certain period of time through cached copies on the CDN. Cloudinary's client libraries wrap the API and simplify the renaming with the rename method. For example, renaming a video with the public ID of old_name to new_name:

Ruby:
Cloudinary::Uploader.rename('old_name', 'new_name', 
            :resource_type => :video)
PHP:
\Cloudinary\Uploader::rename('old_name', 'new_name',
            array("resource_type" => "video"));
Python:
cloudinary.uploader.rename('old_name', 'new_name', 
            resource_type = "video")
Node.js:
cloudinary.uploader.rename('old_name', 'new_name', 
            function(result) { console.log(result) }, 
            { resource_type: "video" })
Java:
cloudinary.uploader().rename("old_name", "new_name",
            ObjectUtils.asMap("resource_type", "video"));

You can also rename the public ID of videos uploaded to Cloudinary by sending an HTTPS POST request to the following URL (replace 'demo' with your cloud name):

https://api.cloudinary.com/v1_1/demo/video/rename

Required parameters:

  • from_public_id - The current identifier of the uploaded video.
  • to_public_id - The new identifier to assign to the uploaded video.
  • api_key - Your unique Cloudinary API Key.
  • timestamp - Unix time in seconds of the current time.
  • signature - A signature of all request parameters, based on your Cloudinary API Secret. See Creating API authentication signatures for more details.

Optional parameters:

  • overwrite - (Boolean) Whether to overwrite an existing video with the target public ID. Default: false.

Tagging videos

Cloudinary allows you to tag uploaded videos. Each video can be assigned one or more tags, which is a short name that you can dynamically use (no need to predefine tags). You can assign tags to videos while uploading them with the tags parameter, and you can also use our API and Management Console for adding, removing or changing tags assigned to videos. Cloudinary's client libraries wrap the API and simplify the tagging with the add_tag method. For example, adding the tag "animal" to the videos with the public IDs of "dog" and "lion":

Ruby:
Cloudinary::Uploader.add_tag('animal', ['dog', 'lion'],
            :resource_type => :video)
PHP:
\Cloudinary\Uploader::add_tag('animal', array('dog', 'lion'),
            array("resource_type" => "video"));
Python:
cloudinary.uploader.add_tag('animal', ['dog', 'lion'],
            resource_type = "video")
Node.js:
cloudinary.uploader.add_tag('animal', [ 'dog', 'lion' ],
            function(result) { console.log(result) }, 
            { resource_type: "video" });
Java:
Map addTagResult = cloudinary.uploader().addTag("animal",
            ["dog", "lion"], 
            ObjectUtils.asMap("resource_type", "video"));

You can also manage the tags of videos already uploaded to Cloudinary by sending an HTTPS POST request to the following URL (replace 'demo' with your cloud name):

https://api.cloudinary.com/v1_1/demo/video/tags

Required parameters:

  • tag - The tag name to assign or remove.
  • public_ids - A list of Public IDs of videos uploaded to Cloudinary.
  • api_key - Your unique Cloudinary API Key.
  • timestamp - Unix time in seconds of the current time.
  • signature - A signature of all request parameters, based on your Cloudinary API Secret. See Creating API authentication signatures for more details.
  • command - The action to perform on video resources using the given tag. Supported values:
    • add - Assign the given tag to the videos with the given Public IDs.
    • remove - Remove the given tag from the videos with the given Public IDs.
    • replace - Assign the given tag to the videos with the given Public IDs while clearing all other tags assigned to these videos.

Assigning tags to videos allows you to create group actions on videos that share the same tag. For example, using the resources_by_tag method of the API to list all videos that share the tag "mytag":

URL:

GET /resources/video/tags/mytag

Code:

Ruby:
Cloudinary::Api.resources_by_tag('mytag', :resource_type => :video)
PHP:
$api->resources_by_tag("mytag", array("resource_type" => "video"));
Python:
cloudinary.api.resources_by_tag("mytag", resource_type = "video")
Node.js:
cloudinary.api.resources_by_tag("mytag", function(result) {
            console.log(result) }, { resource_type: "video" });
Java:
api.resourcesByTag("mytag", 
            ObjectUtils.asMap("resource_type", "video"));