Adding captions to your video files can help users to locate and understand your videos. To add captions to a video, you need to create a file containing the captions and then provide that file to YouTube.
This section discusses the caption file formats that YouTube supports. It also explains the API operations that you can use to create, retrieve, update and delete caption files.
Please note the following requirements for executing caption-related API operations:
Captions are only available for API version 2.
Captions for a video can only be created, retrieved, modified and deleted by the owner of that video. To perform these operations for a video, you must submit authenticated API requests for which the video's owner is the logged-in user. Accordingly, API requests for caption operations must contain a properly formatted Authorization header.
Requests to create (POST), update (PUT) or delete (DELETE) captions must identify your developer key using either the X-GData-Key HTTP header or the key request parameter.
YouTube supports many different formats for caption files, including RealText (.rt), SAMI (.smi) and Media RSS. If you already have captions available, we recommend that you upload them in their original format, whatever that may be. If you do not have formatted caption data, such as a transcript that does not have timing data, we recommend using SubRip (*.SRT) or SubViewer (*.SUB) for generating formatted captions.
YouTube also supports a simple format that is compatible with both the SubRip and SubViewer formats. In this simple format, each caption is divided into three segments that appear in the following order:
Timecodes specify the time and duration that YouTube should display a caption in HH:MM:SS.FS format. Timecodes, which are measured from the beginning of the video, contain the following units
YouTube supports the following time constructs:
The caption text consists of one or more lines of text that will be displayed on the screen during the time offsets. You must use UTF-8 encoding for the caption text.
A blank line marks the end of each caption.
The following example demonstrates this simple caption format:
0:01:23.000,0:01:25.000 This text displays for two seconds starting 1 minute and 23 seconds into the video. 0:02:20.250,0:02:23.8 This text displays from 2 minutes and 20.25 seconds after the start of the video until 2 minutes and 23.8 seconds after the start of the video. 0:03:14.159 This text displays beginning 3 minutes and 14.159 seconds after the start of the video for an undefined length of time.
Each video entry contains a <link> tag for which the rel attribute value is http://gdata.youtube.com/schemas/2007#video.captionTracks. (Note that this link is only visible to the owner of a video.) The tag's href attribute identifies the captions URL for the video.
<link rel="http://gdata.youtube.com/schemas/2007#video.captionTracks"
type="application/atom+xml"
href="http://gdata.youtube.com/feeds/api/videos/ZTUVgYoeN_b/captions"
yt:hasEntries="true|false"/>
Caption tracks are available for a video if the <link> tag's yt:hasEntries attribute has a value of true. If caption tracks are available for the video, you can retrieve the list of tracks by submitting an HTTP GET request to the URL in the link tag. You can use any of the following input parameters in a request to retrieve caption tracks:
The following sample API response shows a caption tracks feed with a single entry:
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:app='http://www.w3.org/2007/app' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:gd='http://schemas.google.com/g/2005' xmlns:xml='http://www.w3.org/XML/1998/namespace' gd:etag='W/"DkcNRH4zfSp7ImA9WxJXEUk."'> <id>tag:youtube.com,2008:videos:PjLv88-zqkI:captions</id> <updated>2009-06-04T19:34:55.085Z</updated> <category scheme='http://schemas.google.com/g/2005#kind' term='http://gdata.youtube.com/schemas/2007#captionTrack'/> <title>Caption Tracks for Video XYZ</title> <logo>http://www.youtube.com/img/pic_youtubelogo_123x63.gif</logo> <link rel='related' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI?v=2'/> <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captions?v=2'/> <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captions?v=2'/> <link rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captions/batch?v=2'/> <link rel='self' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captions?...'/> <link rel='service' type='application/atomsvc+xml' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captions?alt=...'/> <author> <name>andyland74</name> <uri>http://gdata.youtube.com/feeds/api/users/andyland74</uri> </author> <generator version='2.0' uri='http://gdata.youtube.com/'>YouTube data API</generator> <openSearch:totalResults>1</openSearch:totalResults> <openSearch:startIndex>1</openSearch:startIndex> <openSearch:itemsPerPage>25</openSearch:itemsPerPage> <entry gd:etag='W/"DkECQHk5cSp7ImA9WxJSGEw."'> <id>tag:youtube.com,2008:captions:CiELEO...</id> <published>2009-05-08T13:31:01.729-07:00</published> <updated>2009-05-08T13:31:01.729-07:00</updated> <app:edited>2009-05-08T13:31:01.729-07:00</app:edited> <category scheme='http://schemas.google.com/g/2005#kind' term='http://gdata.youtube.com/schemas/2007#captionTrack'/> <title>Sample 3</title> <content type='application/vnd.youtube.timedtext' src='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captiondata/CiELEO...' xml:lang='en'/> <link rel='self' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captions/CiELEO...'/> <link rel='edit' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captions/CiELEO...'/> <link rel='edit-media' type='application/vnd.youtube.timedtext' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captiondata/CiELEO...'/> </entry> </feed>
To create a caption track, post a caption file to the http://schemas.google.com/g/2005#post link for the captions track feed.
You must set the Content-Type header value to the following value:
application/vnd.youtube.timedtext
You should use the Content-Language header to specify the language of the caption track. If you do not specify a language, the API server will attempt to identify the language. However, if the identification fails, then your API request will also fail.
If you do specify the caption track language, then you must also specify the character set used so that YouTube can decode the file. We recommend that you use UTF-8 encoding whenever possible. To specify the character set, add the charset parameter to the Content-Type header value as shown below:
application/vnd.youtube.timedtext; charset=UTF-8
You can use the Slug header to specify a title for the caption track. If you do not specify a title, the API server will use the language as the title of the caption track.
The caption file must be 1MB or smaller.
The following sample API request demonstrates how to create a caption track:
POST /feeds/api/videos/VIDEO_ID/captions HTTP/1.1 Host: gdata.youtube.com Content-Type: application/vnd.youtube.timedtext; charset=UTF-8 Content-Language: en Slug: Title of caption track Authorization: AuthSub token="AUTHORIZATION_TOKEN" GData-Version: 2 X-GData-Client: CLIENT_ID X-GData-Key: key=DEVELOPER_KEY <Caption File Data>
If YouTube successfully handles your request, the API will return a 201 HTTP response code. The Location header in the API response will contain the self link of the caption track entry, which can be used for later retrieval of the entry. The body of the XML response will be the caption track entry.
The XML below shows a successful response to a request to create a caption track:
HTTP 201 Content-Type: application/atom+xml; charset=UTF-8; type=entry Location: http://gdata.youtube.com/feeds/api/captions/VIDEO_ID/captions/caption_track_id <entry xmlns='http://www.w3.org/2005/Atom' xmlns:app='http://www.w3.org/2007/app' xmlns:gd='http://schemas.google.com/g/2005' xmlns:xml='http://www.w3.org/XML/1998/namespace' gd:etag='W/"DEMCSXc7fip7ImA9WxJXEk4."'> <id>tag:youtube.com,2008:captions:CiULE...</id> <published>2009-06-05T14:14:28.906-07:00</published> <updated>2009-06-05T14:14:28.906-07:00</updated> <app:edited>2009-06-05T14:14:28.906-07:00</app:edited> <category scheme='http://schemas.google.com/g/2005#kind' term='http://gdata.youtube.com/schemas/2007#captionTrack'/> <title>API captions</title> <content type='application/vnd.youtube.timedtext' src='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captiondata/CiULE...' xml:lang='en'/> <link rel='self' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captions/CiULE...'/> <link rel='edit' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captions/CiULE...'/> <link rel='edit-media' type='application/vnd.youtube.timedtext' href='http://gdata.youtube.com/feeds/api/videos/PjLv88-zqkI/captiondata/CiULE...'/> </entry>
If your HTTP request is properly formatted, but YouTube cannot process the captions file you are sending, YouTube will still create an <entry> in the captions feed for the new caption track. The entry will contain an <app:control> tag, which indicates that YouTube did not successfully handle the captions file. That tag, in turn, will contain a <yt:state> tag that contains more information about the failure and an <app:draft> tag that contains a value of yes, which indicates that the track is not publicly visible.
<app:control> <app:draft>yes</app:draft> <yt:state name="failed" reasonCode="invalidFormat"/> </app:control>
Caption tracks are served automatically to the YouTube video players, which means that anyone watching a video can opt to view any caption track for that video. However, you can still retrieve a caption track if you want to modify the caption data or the timecodes that specify when the captions display.
To retrieve a caption track, send an HTTP GET request to the src URL specified in the <content> tag of the caption track entry:
<content type="text/xml" xml:lang="zh-HK" src="http://gdata.youtube.com/api/captiondata/caption-id"/>
The API does not return an Atom feed in response to a request for a caption track. Instead, the response contains your caption track in the same format that you uploaded it to YouTube. See the Supported formats for caption files section for details about valid caption file formats.
The API enables you to update the captions and timecodes for a caption track. However, you cannot update metadata about the track. So, for example, you cannot update the title or language of a caption track. If the title and/or language of a caption track is incorrect, you need to delete the track with the incorrect information and create a new track with the corrected title and language.
To update a caption track, send an HTTP PUT request to the edit-media link in the caption track entry:
<link rel="edit-media" type="application/atml+xml" href="http:/gdata.youtube.com/feeds/api/videos/VIDEO_ID/captiondata/CAPTION_ID" />
Your API request must set the Content-Type header value as described in the Creating a caption track section. In addition, your caption file must be 1MB or smaller. The request below demonstrates how to update a caption track:
PUT /feeds/api/videos/VIDEO_ID/captiondata/CAPTION_TRACK_ID HTTP/1.1 Host: gdata.youtube.com Content-Type: application/vnd.youtube.timedtext; charset=UTF-8 Authorization: AuthSub token="AUTHORIZATION_TOKEN" GData-Version: 2 X-GData-Client: CLIENT_ID X-GData-Key: key=DEVELOPER_KEY <Binary Caption File Data>
The updated caption track must be in a supported format for caption files.
To delete a caption track, send an HTTP DELETE request to the edit link in the caption track entry. The following sample API request demonstrates how to delete a caption track:
DELETE /feeds/api/videos/VIDEO_ID/captions/CAPTION_TRACK_ID HTTP/1.1 Host: gdata.youtube.com Authorization: AuthSub token="AUTHORIZATION_TOKEN" GData-Version: 2 X-GData-Client: CLIENT_ID X-GData-Key: key=DEVELOPER_KEY