Skip to content
This repository was archived by the owner on Aug 12, 2025. It is now read-only.

Commit 9a0e1d7

Browse files
"Added sample: php/captions.php"
1 parent 1753c2d commit 9a0e1d7

1 file changed

Lines changed: 388 additions & 0 deletions

File tree

php/captions.php

Lines changed: 388 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,388 @@
1+
<?php
2+
3+
/**
4+
* This sample creates and manages caption tracks by:
5+
*
6+
* 1. Uploading a caption track for a video via "captions.insert" method.
7+
* 2. Getting the caption tracks for a video via "captions.list" method.
8+
* 3. Updating an existing caption track via "captions.update" method.
9+
* 4. Download a caption track via "captions.download" method.
10+
* 5. Deleting an existing caption track via "captions.delete" method.
11+
*
12+
* @author Ibrahim Ulukaya
13+
*/
14+
15+
$htmlBody = <<<END
16+
<form method="GET">
17+
<div>
18+
Action:
19+
<select id="action" name="action">
20+
<option value="upload">Upload - Fill in: video ID, caption track name, language and file</option>
21+
<option value="list">List - Fill in: video ID</option>
22+
<option value="update">Update - Fill in: caption track ID, (optional - caption track file)</option>
23+
<option value="download">Download - Fill in: caption track ID</option>
24+
<option value="delete">Delete - Fill in: caption track ID</option>
25+
<option value="all">All - Fill in: video ID, caption track name, language and file</option>
26+
</select>
27+
</div>
28+
<br>
29+
<div>
30+
Video ID: <input type="text" id="videoId" name="videoId" placeholder="Enter Video ID">
31+
</div>
32+
<br>
33+
<div>
34+
Caption Track Name: <input type="text" id="captionName" name="captionName" placeholder="Enter Caption Track Name">
35+
</div>
36+
<br>
37+
<div>
38+
Caption Track Language: <input type="text" id="captionLanguage" name="captionLanguage" placeholder="Enter Caption Track Language">
39+
</div>
40+
<br>
41+
<div>
42+
File: <input type="file" id ="captionFile" name="captionFile" accept="*/*">
43+
</div>
44+
<br>
45+
<div>
46+
Caption Track Id: <input type="text" id="captionId" name="captionId" placeholder="Enter Caption Track ID">
47+
</div>
48+
<br>
49+
<input type="submit" value="GO!">
50+
</form>
51+
END;
52+
53+
// Call set_include_path() as needed to point to your client library.
54+
require_once 'Google/Client.php';
55+
require_once 'Google/Service/YouTube.php';
56+
session_start();
57+
58+
59+
/*
60+
* You can acquire an OAuth 2.0 client ID and client secret from the
61+
* {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
62+
* For more information about using OAuth 2.0 to access Google APIs, please see:
63+
* <https://developers.google.com/youtube/v3/guides/authentication>
64+
* Please ensure that you have enabled the YouTube Data API for your project.
65+
*/
66+
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
67+
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';
68+
69+
$action = $_GET['action'];
70+
$videoId = $_GET['videoId'];
71+
$captionFile = $_GET['captionFile'];
72+
$captionName = $_GET['captionName'];
73+
$captionLanguage = $_GET['captionLanguage'];
74+
$captionId = $_GET['captionId'];
75+
76+
$client = new Google_Client();
77+
$client->setClientId($OAUTH2_CLIENT_ID);
78+
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
79+
80+
/*
81+
* This OAuth 2.0 access scope allows for full read/write access to the
82+
* authenticated user's account and requires requests to use an SSL connection.
83+
*/
84+
$client->setScopes('https://www.googleapis.com/auth/youtube.force-ssl');
85+
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
86+
FILTER_SANITIZE_URL);
87+
$client->setRedirectUri($redirect);
88+
89+
// Define an object that will be used to make all API requests.
90+
$youtube = new Google_Service_YouTube($client);
91+
92+
if (isset($_GET['code'])) {
93+
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
94+
die('The session state did not match.');
95+
}
96+
97+
$client->authenticate($_GET['code']);
98+
$_SESSION['token'] = $client->getAccessToken();
99+
header('Location: ' . $redirect);
100+
}
101+
102+
if (isset($_SESSION['token'])) {
103+
$client->setAccessToken($_SESSION['token']);
104+
}
105+
106+
// Check to ensure that the access token was successfully acquired.
107+
if ($client->getAccessToken()) {
108+
// This code executes if the user enters an action in the form
109+
// and submits the form. Otherwise, the page displays the form above.
110+
if ($_GET['action']) {
111+
try {
112+
switch ($action) {
113+
case 'upload':
114+
uploadCaption($youtube, $client, $videoId, $captionFile,
115+
$captionName, $captionLanguage, $htmlBody);
116+
break;
117+
case 'list':
118+
$captions = listCaptions($youtube, $videoId, $htmlBody);
119+
break;
120+
case 'update':
121+
updateCaption($youtube, $client, $captionId, $htmlBody, $captionFile);
122+
break;
123+
case 'download':
124+
downloadCaption($youtube, $captionId, $htmlBody);
125+
break;
126+
case 'delete':
127+
deleteCaption($youtube, $captionId, $htmlBody);
128+
break;
129+
default:
130+
# All the available methods are used in sequence just for the sake of an example.
131+
uploadCaption($youtube, $client, $videoId, $captionFile,
132+
$captionName, $captionLanguage, $htmlBody);
133+
134+
$captions = listCaptions($youtube, $videoId, $htmlBody);
135+
136+
if (empty($captions)) {
137+
$htmlBody .= "<h3>Can't get video caption tracks.</h3>";
138+
} else {
139+
$firstCaptionId = $captions[0]['id'];
140+
updateCaption($youtube, $client, $firstCaptionId, $htmlBody, null);
141+
downloadCaption($youtube, $firstCaptionId, $htmlBody);
142+
deleteCaption($youtube, $firstCaptionId, $htmlBody);
143+
}
144+
}
145+
} catch (Google_Service_Exception $e) {
146+
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
147+
htmlspecialchars($e->getMessage()));
148+
} catch (Google_Exception $e) {
149+
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
150+
htmlspecialchars($e->getMessage()));
151+
}
152+
}
153+
$_SESSION['token'] = $client->getAccessToken();
154+
} else {
155+
// If the user hasn't authorized the app, initiate the OAuth flow
156+
$state = mt_rand();
157+
$client->setState($state);
158+
$_SESSION['state'] = $state;
159+
160+
$authUrl = $client->createAuthUrl();
161+
$htmlBody = <<<END
162+
<h3>Authorization Required</h3>
163+
<p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
164+
END;
165+
}
166+
167+
/**
168+
* Uploads a caption track in draft status that matches the API request parameters.
169+
* (captions.insert)
170+
*
171+
* @param Google_Service_YouTube $youtube YouTube service object.
172+
* @param Google_Client $client Google client.
173+
* @param $videoId the YouTube video ID of the video for which the API should
174+
* return caption tracks.
175+
* @param $captionLanguage language of the caption track.
176+
* @param $captionName name of the caption track.
177+
* @param $captionFile caption track binary file.
178+
* @param $htmlBody html body.
179+
*/
180+
function uploadCaption(Google_Service_YouTube $youtube, Google_Client $client, $videoId,
181+
$captionFile, $captionName, $captionLanguage, &$htmlBody) {
182+
# Insert a video caption.
183+
# Create a caption snippet with video id, language, name and draft status.
184+
$captionSnippet = new Google_Service_YouTube_CaptionSnippet();
185+
$captionSnippet->setVideoId($videoId);
186+
$captionSnippet->setLanguage($captionLanguage);
187+
$captionSnippet->setName($captionName);
188+
189+
# Create a caption with snippet.
190+
$caption = new Google_Service_YouTube_Caption();
191+
$caption->setSnippet($captionSnippet);
192+
193+
// Specify the size of each chunk of data, in bytes. Set a higher value for
194+
// reliable connection as fewer chunks lead to faster uploads. Set a lower
195+
// value for better recovery on less reliable connections.
196+
$chunkSizeBytes = 1 * 1024 * 1024;
197+
198+
// Setting the defer flag to true tells the client to return a request which can be called
199+
// with ->execute(); instead of making the API call immediately.
200+
$client->setDefer(true);
201+
202+
// Create a request for the API's captions.insert method to create and upload a caption.
203+
$insertRequest = $youtube->captions->insert("snippet", $caption);
204+
205+
// Create a MediaFileUpload object for resumable uploads.
206+
$media = new Google_Http_MediaFileUpload(
207+
$client,
208+
$insertRequest,
209+
'*/*',
210+
null,
211+
true,
212+
$chunkSizeBytes
213+
);
214+
$media->setFileSize(filesize($captionFile));
215+
216+
217+
// Read the caption file and upload it chunk by chunk.
218+
$status = false;
219+
$handle = fopen($captionFile, "rb");
220+
while (!$status && !feof($handle)) {
221+
$chunk = fread($handle, $chunkSizeBytes);
222+
$status = $media->nextChunk($chunk);
223+
}
224+
225+
fclose($handle);
226+
227+
// If you want to make other calls after the file upload, set setDefer back to false
228+
$client->setDefer(false);
229+
230+
$htmlBody .= "<h2>Inserted video caption track for</h2><ul>";
231+
$captionSnippet = $status['snippet'];
232+
$htmlBody .= sprintf('<li>%s(%s) in %s language, %s status.</li>',
233+
$captionSnippet['name'], $status['id'], $captionSnippet['language'],
234+
$captionSnippet['status']);
235+
$htmlBody .= '</ul>';
236+
}
237+
238+
/**
239+
* Returns a list of caption tracks. (captions.listCaptions)
240+
*
241+
* @param Google_Service_YouTube $youtube YouTube service object.
242+
* @param string $videoId The videoId parameter instructs the API to return the
243+
* caption tracks for the video specified by the video id.
244+
* @param $htmlBody - html body.
245+
*/
246+
function listCaptions(Google_Service_YouTube $youtube, $videoId, &$htmlBody) {
247+
// Call the YouTube Data API's captions.list method to retrieve video caption tracks.
248+
$captions = $youtube->captions->listCaptions("snippet", $videoId);
249+
250+
$htmlBody .= "<h3>Video Caption Tracks</h3><ul>";
251+
foreach ($captions as $caption) {
252+
$htmlBody .= sprintf('<li>%s(%s) in %s language</li>', $caption['snippet']['name'],
253+
$caption['id'], $caption['snippet']['language']);
254+
}
255+
$htmlBody .= '</ul>';
256+
257+
return $captions;
258+
}
259+
260+
/**
261+
* Updates a caption track's draft status to publish it.
262+
* Updates the track with a new binary file as well if it is present. (captions.update)
263+
*
264+
* @param Google_Service_YouTube $youtube YouTube service object.
265+
* @param Google_Client $client Google client.
266+
* @param string $captionId The id parameter specifies the caption ID for the resource
267+
* that is being updated. In a caption resource, the id property specifies the
268+
* caption track's ID.
269+
* @param $htmlBody - html body.
270+
* @param $captionFile caption track binary file.
271+
*/
272+
function updateCaption(Google_Service_YouTube $youtube, Google_Client $client,
273+
$captionId, &$htmlBody, $captionFile) {
274+
// Modify caption's isDraft property to unpublish a caption track.
275+
$updateCaptionSnippet = new Google_Service_YouTube_CaptionSnippet();
276+
$updateCaptionSnippet->setIsDraft(true);
277+
278+
# Create a caption with snippet.
279+
$updateCaption = new Google_Service_YouTube_Caption();
280+
$updateCaption->setSnippet($updateCaptionSnippet);
281+
$updateCaption->setId($captionId);
282+
283+
if ($captionFile == '')
284+
{
285+
// Call the YouTube Data API's captions.update method to update an existing caption track.
286+
$captionUpdateResponse = $youtube->captions->update("snippet", $updateCaption);
287+
288+
$htmlBody .= "<h2>Updated caption track</h2><ul>";
289+
$htmlBody .= sprintf('<li>%s(%s) draft status: %s</li>',
290+
$captionUpdateResponse['snippet']['name'],
291+
$captionUpdateResponse['id'], $captionUpdateResponse['snippet']['isDraft']);
292+
$htmlBody .= '</ul>';
293+
} else {
294+
// Specify the size of each chunk of data, in bytes. Set a higher value for
295+
// reliable connection as fewer chunks lead to faster uploads. Set a lower
296+
// value for better recovery on less reliable connections.
297+
$chunkSizeBytes = 1 * 1024 * 1024;
298+
299+
// Setting the defer flag to true tells the client to return a request which can be called
300+
// with ->execute(); instead of making the API call immediately.
301+
$client->setDefer(true);
302+
303+
// Create a request for the YouTube Data API's captions.update method to update
304+
// an existing caption track.
305+
$captionUpdateRequest = $youtube->captions->update("snippet", $updateCaption);
306+
307+
// Create a MediaFileUpload object for resumable uploads.
308+
$media = new Google_Http_MediaFileUpload(
309+
$client,
310+
$captionUpdateRequest,
311+
'*/*',
312+
null,
313+
true,
314+
$chunkSizeBytes
315+
);
316+
$media->setFileSize(filesize($captionFile));
317+
318+
// Read the caption file and upload it chunk by chunk.
319+
$status = false;
320+
$handle = fopen($captionFile, "rb");
321+
while (!$status && !feof($handle)) {
322+
$chunk = fread($handle, $chunkSizeBytes);
323+
$status = $media->nextChunk($chunk);
324+
}
325+
326+
fclose($handle);
327+
328+
// If you want to make other calls after the file upload, set setDefer back to false
329+
$client->setDefer(false);
330+
331+
$htmlBody .= "<h2>Updated caption track</h2><ul>";
332+
$htmlBody .= sprintf('<li>%s(%s) draft status: %s and updated the track with
333+
the new uploaded file.</li>',
334+
$status['snippet']['name'], $status['id'], $status['snippet']['isDraft']);
335+
$htmlBody .= '</ul>';
336+
}
337+
}
338+
339+
/**
340+
* Downloads a caption track for a YouTube video. (captions.download)
341+
*
342+
* @param Google_Service_YouTube $youtube YouTube service object.
343+
* @param string $captionId The id parameter specifies the caption ID for the resource
344+
* that is being downloaded. In a caption resource, the id property specifies the
345+
* caption track's ID.
346+
* @param $htmlBody - html body.
347+
*/
348+
function downloadCaption(Google_Service_YouTube $youtube, $captionId, &$htmlBody) {
349+
// Call the YouTube Data API's captions.download method to download an existing caption.
350+
$captionResouce = $youtube->captions->download($captionId, array(
351+
'tfmt' => "srt",
352+
'alt' => "media"
353+
));
354+
355+
$htmlBody .= "<h2>Downloaded caption track</h2><ul>";
356+
$htmlBody .= sprintf('<li>%s</li>',
357+
$captionResouce);
358+
$htmlBody .= '</ul>';
359+
}
360+
361+
/**
362+
* Deletes a caption track for a YouTube video. (captions.delete)
363+
*
364+
* @param Google_Service_YouTube $youtube YouTube service object.
365+
* @param string $captionId The id parameter specifies the caption ID for the resource
366+
* that is being deleted. In a caption resource, the id property specifies the
367+
* caption track's ID.
368+
* @param $htmlBody - html body.
369+
*/
370+
function deleteCaption(Google_Service_YouTube $youtube, $captionId, &$htmlBody) {
371+
// Call the YouTube Data API's captions.delete method to delete a caption.
372+
$youtube->captions->delete($captionId);
373+
374+
$htmlBody .= "<h2>Deleted caption track</h2><ul>";
375+
$htmlBody .= sprintf('<li>%s</li>',$captionId);
376+
$htmlBody .= '</ul>';
377+
}
378+
?>
379+
380+
<!doctype html>
381+
<html>
382+
<head>
383+
<title>Create and manage video caption tracks</title>
384+
</head>
385+
<body>
386+
<?=$htmlBody?>
387+
</body>
388+
</html>

0 commit comments

Comments
 (0)