我正在运行一个 ffmpeg 的WordPress网站,允许用户使用表单创建视频。视频工作正常,每个帖子都保存在自己的目录中。
我现在正试图允许用户将他们创建的视频上传到自己的YouTube频道。
使用youtube api中的PHP代码以及Google控制台中的我的应用程序,我能够将视频成功上传到自己的帐户中。它只要求我进行一次身份验证。
PHP代码-
s:815:"a:4:{i:0;a:7:{s:4:"date";s:10:"2018-03-08";s:4:"time";s:7:"1:00 am";s:8:"location";s:4:"test";s:12:"updated-name";s:7:"wpcargo";s:10:"updated-by";i:2;s:7:"remarks";s:1:"1";s:6:"status";s:16:"Shipment Left US";}i:1;a:7:{s:4:"date";s:10:"2018-03-08";s:4:"time";s:7:"1:00 am";s:8:"location";s:4:"test";s:12:"updated-name";s:7:"wpcargo";s:10:"updated-by";i:2;s:7:"remarks";s:1:"1";s:6:"status";s:10:"Processing";}i:2;a:7:{s:4:"date";s:10:"2018-09-12";s:4:"time";s:7:"7:27 pm";s:8:"location";s:4:"test";s:12:"updated-name";s:7:"wpcargo";s:10:"updated-by";i:2;s:7:"remarks";s:1:"1";s:6:"status";s:10:"In Transit";}i:3;a:7:{s:4:"date";s:10:"2018-09-12";s:4:"time";s:7:"7:31 pm";s:8:"location";s:10:"tofindthis";s:12:"updated-name";s:7:"wpcargo";s:10:"updated-by";i:2;s:7:"remarks";s:1:"1";s:6:"status";s:10:"In Transit";}}";
我也已经成功地能够遵循javascript示例从计算机上载文件,但是文件存储在服务器上,所以这不是我想要的。
使用javascript,似乎可以为用户获取新令牌,但文件上传问题除外,并且用户必须进入其Google帐户才能撤消对我的网站应用程序的访问/注销。
JS代码-
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/gap/google-api-php-client/vendor/autoload.php';
$key = file_get_contents('the_key.txt');
set_include_path($_SERVER['DOCUMENT_ROOT'] . '/gap/google-api-php-client/');
require_once 'src/Google/Client.php';
require_once 'src/Google/Service/YouTube.php';
$application_name = 'youtube4true';
$OAUTH2_CLIENT_ID = 'REMOVED FOR STACK';
$OAUTH2_CLIENT_SECRET = 'REMOVED FOR STACK';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('https://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
$client->setAccessType("offline");
$client->setApprovalPrompt("force");
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION[$tokenSessionKey])) {
$client->setAccessToken($_SESSION[$tokenSessionKey]);
$refresh_token = $_SESSION[$tokenSessionKey]['refresh_token'];
file_put_contents('the_key.txt', $refresh_token);
} elseif(file_exists('the_key.txt')) {
$refresh_token = file_get_contents('the_key.txt');
$client->refreshToken($refresh_token);
$_SESSION['token'] = $client->getAccessToken();
$access_token = $_SESSION['token']['access_token'];
$client->setAccessToken($access_token);
$refresh_token = $_SESSION['token']['refresh_token'];
file_put_contents('the_key.txt', $refresh_token);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
$htmlBody = '';
try{
// REPLACE this value with the path to the file you are uploading.
$videoPath = "HERE I WILL USE AJAX TO PASS THE PATH TO THE VIDEO FILE";
// Create a snippet with title, description, tags and category ID
// Create an asset resource and set its snippet metadata and type.
// This example sets the video's title, description, keyword tags, and
// video category.
$snippet = new Google_Service_YouTube_VideoSnippet();
$snippet->setTitle("Test title");
$snippet->setDescription("Test description");
$snippet->setTags(array("tag1", "tag2"));
// Numeric video category. See
// https://developers.google.com/youtube/v3/docs/videoCategories/list
$snippet->setCategoryId("22");
// Set the video's status to "public". Valid statuses are "public",
// "private" and "unlisted".
$status = new Google_Service_YouTube_VideoStatus();
$status->privacyStatus = "public";
// Associate the snippet and status objects with a new video resource.
$video = new Google_Service_YouTube_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$chunkSizeBytes = 1 * 1024 * 1024;
// Setting the defer flag to true tells the client to return a request which can be called
// with ->execute(); instead of making the API call immediately.
$client->setDefer(true);
// Create a request for the API's videos.insert method to create and upload the video.
$insertRequest = $youtube->videos->insert("status,snippet", $video);
// Create a MediaFileUpload object for resumable uploads.
$media = new Google_Http_MediaFileUpload(
$client,
$insertRequest,
'video/*',
null,
true,
$chunkSizeBytes
);
$media->setFileSize(filesize($videoPath));
// Read the media file and upload it chunk by chunk.
$status = false;
$handle = fopen($videoPath, "rb");
while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
try {
// Call the channels.list method to retrieve information about the
// currently authenticated user's channel.
$channelsResponse = $youtube->channels->listChannels('contentDetails', array(
'mine' => 'true',
));
$htmlBody = '';
foreach ($channelsResponse['items'] as $channel) {
// Extract the unique playlist ID that identifies the list of videos
// uploaded to the channel, and then call the playlistItems.list method
// to retrieve that list.
$uploadsListId = $channel['contentDetails']['relatedPlaylists']['uploads'];
$playlistItemsResponse = $youtube->playlistItems->listPlaylistItems('snippet', array(
'playlistId' => $uploadsListId,
'maxResults' => 50
));
$htmlBody .= "<h3>Videos in list $uploadsListId</h3><ul>";
foreach ($playlistItemsResponse['items'] as $playlistItem) {
$htmlBody .= sprintf('<li>%s (%s)</li>', $playlistItem['snippet']['title'],
$playlistItem['snippet']['resourceId']['videoId']);
}
$htmlBody .= '</ul>';
}
} catch (Google_ServiceException $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
$_SESSION['token'] = $client->getAccessToken();
} else {
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to <a href="$authUrl">authorise access</a> before proceeding.<p>
END;
}
?>
<!doctype html>
<html>
<head>
<title>Video Uploaded</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
我很确定这与刷新或访问令牌有关。那么,如何为每个用户创建访问令牌,而不是只允许我在应用程序上使用我的帐户?
答案 0 :(得分:3)
您需要执行the OAUTH dance
Google在此过程中有good documentation。以下引用的内容和代码是从该站点提取的。
- 您的应用程序标识了所需的权限。
- 您的应用程序将用户与请求的权限列表一起重定向到Google。
- 用户决定是否向您的应用授予权限。
- 您的应用程序可以找出用户的决定。
- 如果用户授予了请求的权限,则您的应用程序将检索代表用户发出API请求所需的令牌。
第1步和第2步的代码
// setup client (step.1)
$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(GOOGLE_SERVICE_YOUTUBE::YOUTUBE_UPLOAD);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
$client->setAccessType('offline'); // offline access
$client->setIncludeGrantedScopes(true); // incremental auth
// get url and redirect (step.2)
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
exit();
您需要设置重定向网址,以接受来自他们的回叫,格式如下:
[your_callback_url]/oauth2callback?state=state_parameter_passthrough_value&code=[code]&scope=[scope]
然后,您从回调中提取详细信息,并将其交换为令牌,以便您上载。
// swap the code for a token (step.5)
// … do client setup first
// then auth with the code
$client->authenticate($_GET['code']);
// retrieve the token
$access_token = $client->getAccessToken();
然后您可以在api调用中使用该令牌代表用户进行调用。
答案 1 :(得分:2)
通过使用页面上的以下表格,我可以按照自己的方式工作-
<form id="publish-youtube" action="/path/to/upload.php" method="post" target="_blank">
<input type="hidden" id="a_id" name="a_id" value="<?php echo $post_author_id; ?>" />
<input type="hidden" id="vid_id" name="vid_id" value="<?php echo $v_Id; ?>" />
<input type="submit" id="ytu_submit" name="ytu_submit" value="Publish to YouTube">
</form>
然后,我按照youtube api docs创建了我的应用和我的upload.php脚本,该脚本要求用户登录(如果尚未登录),并根据表格中的值上传视频(注意: wordpress)-
<?php
//require_once $_SERVER['DOCUMENT_ROOT'] . '/gap/google-api-php-client/vendor/autoload.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php';
set_include_path($_SERVER['DOCUMENT_ROOT'] . '/gap/google-api-php-client/');
require_once 'src/Google/Client.php';
require_once 'src/Google/Service/YouTube.php';
session_start();
$application_name = 'XXXX';
$OAUTH2_CLIENT_ID = 'XXXX';
$OAUTH2_CLIENT_SECRET = 'XXXX';
$videoTitle = $_POST['titlez'];
$authorID = $_POST['a_id'];
$vidID = $_POST['vid_id'];
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('https://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
$client->setAccessType("offline");
$client->setApprovalPrompt("force");
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION[$tokenSessionKey])) {
$client->setAccessToken($_SESSION[$tokenSessionKey]);
}
get_header();
global $current_user, $imic_options; // Use global
get_currentuserinfo(); // Make sure global is set, if not set it.
if ((user_can($current_user, "administrator"))||(user_can($current_user, "edit_others_posts")) ):
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
$htmlBody = '';
try{
// REPLACE this value with the path to the file you are uploading.
$videoPath = $_SERVER["DOCUMENT_ROOT"] ."/uploads/".$authorID."/".$vidID."/output-".$vidID.".mp4";
// Create a snippet with title, description, tags and category ID
// Create an asset resource and set its snippet metadata and type.
// This example sets the video's title, description, keyword tags, and
// video category.
$snippet = new Google_Service_YouTube_VideoSnippet();
$snippet->setTitle("Test title");
$snippet->setDescription("Test description");
$snippet->setTags(array("tag1", "tag2"));
// Numeric video category. See
// https://developers.google.com/youtube/v3/docs/videoCategories/list
$snippet->setCategoryId("22");
// Set the video's status to "public". Valid statuses are "public",
// "private" and "unlisted".
$status = new Google_Service_YouTube_VideoStatus();
$status->privacyStatus = "public";
// Associate the snippet and status objects with a new video resource.
$video = new Google_Service_YouTube_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$chunkSizeBytes = 1 * 1024 * 1024;
// Setting the defer flag to true tells the client to return a request which can be called
// with ->execute(); instead of making the API call immediately.
$client->setDefer(true);
// Create a request for the API's videos.insert method to create and upload the video.
$insertRequest = $youtube->videos->insert("status,snippet", $video);
// Create a MediaFileUpload object for resumable uploads.
$media = new Google_Http_MediaFileUpload(
$client,
$insertRequest,
'video/*',
null,
true,
$chunkSizeBytes
);
$media->setFileSize(filesize($videoPath));
// Read the media file and upload it chunk by chunk.
$status = false;
$handle = fopen($videoPath, "rb");
while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
$htmlBody .= "<h3>Video Uploaded</h3><ul>";
$htmlBody .= sprintf('<li>%s</li>',
$status['snippet']['title']);
$htmlBody .= sprintf('<li><a href="https://www.youtube.com/watch?v=%s" target="_blank">Video Link</a></li>',
$status['id']);
$htmlBody .= '</ul>';
} catch (Google_Service_Exception $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == '(I never changed this)REPLACE_ME') {
$htmlBody = <<<END
<h3>Client Credentials Required</h3>
<p>
You need to set <code>\$OAUTH2_CLIENT_ID</code> and
<code>\$OAUTH2_CLIENT_ID</code> before proceeding.
<p>
END;
} else {
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}
?>
<div id="ytu-container">
<?=$htmlBody?>
</div>
<?php
else: echo imic_unidentified_agent();
endif;
get_footer();
?>