使用 PHP 指定在 Youtube API 中上传视频的频道
Specify the channel to upload the videos in Youtube API using PHP
我的 Google 帐户下有两个频道。我可以使用 Youtube API for PHP 将视频上传到我的主频道。我想将视频上传到我的第二个频道(不是主频道)。我搜索了很多,但找不到解决方案。我刚刚想到的是,我可能需要使用 Google_Service_YouTube_ChannelContentOwnerDetails()
class,但我不知道如何将此细节指定给 https://github.com/youtube/api-samples/blob/master/php/resumable_upload.php 指定的 $youtube->videos->insert("status,snippet", $video)
方法。
我还发现我可能需要使用 onBehalfOfContentOwner
和 onBehalfOfContentOwnerChannel
属性,但我认为这些参数适用于已授予访问权限的帐户其他频道代表他们管理他们的频道,我不需要使用它们,因为我在一个 Google 帐户下拥有我的两个频道。 (也许我错了)。
我只想通过我的主频道授权将视频上传到我的第二个帐户。
在这方面,我们将不胜感激任何帮助。
无法为 Videos.insert
API 端点指定频道 ID。但是请耐心等待...
第一次发出 the OAuth 2.0 authorization flow,his/her 应用收到如下 JSON 对象:
{
"access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
"expires_in": 3920,
"token_type": "Bearer",
"scope": "https://www.googleapis.com/auth/youtube.force-ssl",
"refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}
访问令牌是短暂的,而刷新令牌是长期的(但可以撤销at will). This kind of JSON object gets cached in a local file, for to be used later when the app needs a fresh access token (that is obtained from the API 基于存储的刷新令牌)。访问令牌需要传递到每个需要授权的 API 端点。
以上两个令牌是相对于授权过程中登录的Google帐户而言的。在最常见的情况下,每个 Google 帐户都与特定的 YouTube 帐户(即频道)唯一关联。但是可以有 Google 个帐户与多个 YouTube 频道相关联(请参阅 this doc 部分 使用由您的 Google 帐户管理的品牌帐户 ) .
现在我的猜想:我确实认为一个人可能有N
这样的JSON对象(相对于相同的范围;例如https://www.googleapis.com/auth/youtube.upload
),每个都与不同的 Youtube 频道相关联——都在一个 Google 帐户的保护伞下——所有都存储在本地单独的文件中(甚至都在一个文件中),这样,当发出需要针对给定通道的 API 调用时,以编程方式从整个 N
对象集中选择关联的标记对。
我回答的第二部分包含说明我上述猜想的源代码。我无意在此展示一个完整的 and/or 包罗万象的解决方案,而只是提出一个应用程序框架,以适应具体 PHP 应用程序可能运行的各种方式(例如,单个桌面应用程序或运行 在 未安装浏览器 ) 的远程服务器上自主运行的应用程序。
该应用程序管理一组 JSON 个文件 -- 所有文件都存储在同一目录 ($auth_conf_path
) 中。每个文件都包含与特定通道相关的所需凭据,以便能够从中创建 class Google_Client
的正确实例。这些 JSON 文件的名称格式为 CHANNEL_ID.json
,其中 CHANNEL_ID
是该文件所指频道的 ID。
该应用分为两部分:一部分在启动 OAuth 授权流程时创建这些凭据 JSON 文件;另一个相对于已存在凭据 JSON 文件的给定通道进行 API 调用。
应用程序的第一部分,通过在通常的 PHP OAuth 流程中使用 initChannelCredentials
,生成与应用程序所在的 YouTube 频道相关的 ID 和凭据 JSON 文件授予访问权限。
应用程序的第二部分,在从 makeChannelClient
获得 Google_Client
class 的实例后,进行实际的 API 相对于由传递给该函数的 ID。
function initChannelCredentials(
$auth_conf_path, $scopes, $redirect_uri, $client_code)
{
if (!is_dir($auth_conf_path))
throw new InvalidArgumentException(sprintf(
'Auth config path "%s" does not exist', $auth_conf_path));
$client = new Google_Client();
$client->setAuthConfigFile(
$auth_conf_path . DIRECTORY_SEPARATOR . 'client_secrets.json');
$client->setRedirectUri($redirect_uri);
$client->setScopes($scopes);
$cred = $client->fetchAccessTokenWithAuthCode($client_code);
$youtube = new Google_Service_YouTube($client);
$response = $youtube->channels->listChannels('id', array(
'mine' => 'true'
));
$channel_id = $response[0]['id'];
$cred_file = $auth_conf_path . DIRECTORY_SEPARATOR . $channel_id . '.json';
if (file_exists($cred_file))
throw new InvalidArgumentException(sprintf(
'Credentials file for channel "%s" already exists', $channel_id));
file_put_contents($cred_file, json_encode($cred));
return $channel_id;
}
function makeChannelClient($auth_conf_path, $channel_id)
{
if (!is_dir($auth_conf_path))
throw new InvalidArgumentException(sprintf(
'Auth config path "%s" does not exist', $auth_conf_path));
$cred_file = $auth_conf_path . DIRECTORY_SEPARATOR . $channel_id . '.json';
if (!file_exists($cred_file))
throw new InvalidArgumentException(sprintf(
'Credentials file for channel "%s" does not exist', $channel_id));
if (!$cred = json_decode(file_get_contents($cred_file), true))
throw new LogicException(sprintf(
'Invalid content of credentials file for channel "%s"', $channel_id));
$client = new Google_Client();
$client->setAccessType('offline');
$client->setScopes($cred['scope']);
$client->setAccessToken($cred);
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($cred_file, json_encode($client->getAccessToken()));
}
return $client;
}
请注意,如上所述的应用程序比包含在原始 post 和我上面的推测中的应用程序更通用。应用程序管理的凭据 JSON 文件——同样是 YouTube 频道——不需要在单个 Google 帐户的保护下全部工作(正如我的推测所规定的那样)。这些渠道很可能与不同的 Google 帐户有关,只要此类 PHP 应用程序的具体化身能够正确处理多个 Google 帐户。
我尝试在片段对象中设置“--channelId”,但这似乎不起作用。
解决方法是针对不同的子通道生成不同的oauth2.json。
我的 Google 帐户下有两个频道。我可以使用 Youtube API for PHP 将视频上传到我的主频道。我想将视频上传到我的第二个频道(不是主频道)。我搜索了很多,但找不到解决方案。我刚刚想到的是,我可能需要使用 Google_Service_YouTube_ChannelContentOwnerDetails()
class,但我不知道如何将此细节指定给 https://github.com/youtube/api-samples/blob/master/php/resumable_upload.php 指定的 $youtube->videos->insert("status,snippet", $video)
方法。
我还发现我可能需要使用 onBehalfOfContentOwner
和 onBehalfOfContentOwnerChannel
属性,但我认为这些参数适用于已授予访问权限的帐户其他频道代表他们管理他们的频道,我不需要使用它们,因为我在一个 Google 帐户下拥有我的两个频道。 (也许我错了)。
我只想通过我的主频道授权将视频上传到我的第二个帐户。
在这方面,我们将不胜感激任何帮助。
无法为 Videos.insert
API 端点指定频道 ID。但是请耐心等待...
第一次发出 the OAuth 2.0 authorization flow,his/her 应用收到如下 JSON 对象:
{
"access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
"expires_in": 3920,
"token_type": "Bearer",
"scope": "https://www.googleapis.com/auth/youtube.force-ssl",
"refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}
访问令牌是短暂的,而刷新令牌是长期的(但可以撤销at will). This kind of JSON object gets cached in a local file, for to be used later when the app needs a fresh access token (that is obtained from the API 基于存储的刷新令牌)。访问令牌需要传递到每个需要授权的 API 端点。
以上两个令牌是相对于授权过程中登录的Google帐户而言的。在最常见的情况下,每个 Google 帐户都与特定的 YouTube 帐户(即频道)唯一关联。但是可以有 Google 个帐户与多个 YouTube 频道相关联(请参阅 this doc 部分 使用由您的 Google 帐户管理的品牌帐户 ) .
现在我的猜想:我确实认为一个人可能有N
这样的JSON对象(相对于相同的范围;例如https://www.googleapis.com/auth/youtube.upload
),每个都与不同的 Youtube 频道相关联——都在一个 Google 帐户的保护伞下——所有都存储在本地单独的文件中(甚至都在一个文件中),这样,当发出需要针对给定通道的 API 调用时,以编程方式从整个 N
对象集中选择关联的标记对。
我回答的第二部分包含说明我上述猜想的源代码。我无意在此展示一个完整的 and/or 包罗万象的解决方案,而只是提出一个应用程序框架,以适应具体 PHP 应用程序可能运行的各种方式(例如,单个桌面应用程序或运行 在 未安装浏览器 ) 的远程服务器上自主运行的应用程序。
该应用程序管理一组 JSON 个文件 -- 所有文件都存储在同一目录 ($auth_conf_path
) 中。每个文件都包含与特定通道相关的所需凭据,以便能够从中创建 class Google_Client
的正确实例。这些 JSON 文件的名称格式为 CHANNEL_ID.json
,其中 CHANNEL_ID
是该文件所指频道的 ID。
该应用分为两部分:一部分在启动 OAuth 授权流程时创建这些凭据 JSON 文件;另一个相对于已存在凭据 JSON 文件的给定通道进行 API 调用。
应用程序的第一部分,通过在通常的 PHP OAuth 流程中使用 initChannelCredentials
,生成与应用程序所在的 YouTube 频道相关的 ID 和凭据 JSON 文件授予访问权限。
应用程序的第二部分,在从 makeChannelClient
获得 Google_Client
class 的实例后,进行实际的 API 相对于由传递给该函数的 ID。
function initChannelCredentials(
$auth_conf_path, $scopes, $redirect_uri, $client_code)
{
if (!is_dir($auth_conf_path))
throw new InvalidArgumentException(sprintf(
'Auth config path "%s" does not exist', $auth_conf_path));
$client = new Google_Client();
$client->setAuthConfigFile(
$auth_conf_path . DIRECTORY_SEPARATOR . 'client_secrets.json');
$client->setRedirectUri($redirect_uri);
$client->setScopes($scopes);
$cred = $client->fetchAccessTokenWithAuthCode($client_code);
$youtube = new Google_Service_YouTube($client);
$response = $youtube->channels->listChannels('id', array(
'mine' => 'true'
));
$channel_id = $response[0]['id'];
$cred_file = $auth_conf_path . DIRECTORY_SEPARATOR . $channel_id . '.json';
if (file_exists($cred_file))
throw new InvalidArgumentException(sprintf(
'Credentials file for channel "%s" already exists', $channel_id));
file_put_contents($cred_file, json_encode($cred));
return $channel_id;
}
function makeChannelClient($auth_conf_path, $channel_id)
{
if (!is_dir($auth_conf_path))
throw new InvalidArgumentException(sprintf(
'Auth config path "%s" does not exist', $auth_conf_path));
$cred_file = $auth_conf_path . DIRECTORY_SEPARATOR . $channel_id . '.json';
if (!file_exists($cred_file))
throw new InvalidArgumentException(sprintf(
'Credentials file for channel "%s" does not exist', $channel_id));
if (!$cred = json_decode(file_get_contents($cred_file), true))
throw new LogicException(sprintf(
'Invalid content of credentials file for channel "%s"', $channel_id));
$client = new Google_Client();
$client->setAccessType('offline');
$client->setScopes($cred['scope']);
$client->setAccessToken($cred);
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($cred_file, json_encode($client->getAccessToken()));
}
return $client;
}
请注意,如上所述的应用程序比包含在原始 post 和我上面的推测中的应用程序更通用。应用程序管理的凭据 JSON 文件——同样是 YouTube 频道——不需要在单个 Google 帐户的保护下全部工作(正如我的推测所规定的那样)。这些渠道很可能与不同的 Google 帐户有关,只要此类 PHP 应用程序的具体化身能够正确处理多个 Google 帐户。
我尝试在片段对象中设置“--channelId”,但这似乎不起作用。 解决方法是针对不同的子通道生成不同的oauth2.json。