调用YouTube Data API v3 Captions字幕接口报错 其他接口正常
问题说明
调用YouTube Data API v3的Captions字幕接口(接口地址:https://www.googleapis.com/youtube/v3/captions/id)时返回错误,使用相同的鉴权配置与代码逻辑调用其他YouTube Data API接口均可正常响应,需要对应的排查思路与解决方案。
复现代码
try{ $client = new Google_Client(); $client->setApplicationName('My First Project'); $client_id = get_option('gapi_client_id'); $client_secret = get_option('gapi_client_secret'); $redirect_uri = 'https://income.tube/wp-admin/admin.php?page=rnd-eytes'; $simple_api_key = get_option('rnd-eyts'); $client->setClientId($client_id); $client->setClientSecret($client_secret); $client->setRedirectUri($redirect_uri); $client->setDeveloperKey($simple_api_key); $client->setScopes([ 'https://www.googleapis.com/auth/youtube.force-ssl', 'https://www.googleapis.com/auth/youtube.readonly', 'https://www.googleapis.com/auth/youtubepartner' ]); $client->setAccessType('offline'); echo $authCode = get_option('gapi_auth_code'); $accessToken = $client->fetchAccessTokenWithAuthCode($authCode); $client->setAuthConfig($access_token); // Get the authorized Guzzle HTTP client. $http = $client->authorize(); $fp = fopen(__DIR__ . '/Libs/YOUR_FILE', 'w'); // Exchange authorization code for access token. $accessToken = $client->fetchAccessTokenWithAuthCode($authCode); $queryParams = [ 'tfmt' => 'vtt', 'tlang' => 'fr' ]; $response = $http->request( 'GET', '/youtube/v3/captions/OdIfTQmbuCS8lIzTWpQoHP66BOQh1VfTCmNAH-qo6vE=', [ 'query' => $queryParams ] ); echo '<pre>'; print_r($response); echo '</pre>'; fwrite($fp, $response->getBody()->getContents()); fclose($fp); }catch(Exception $e){ //catch the exception here echo '<pre>'; print_r($e); echo '</pre>'; }
报错参考截图



排查与修复方案
按优先级逐个排查以下问题:
- 修复代码变量名错误:代码中第一次获取access token后赋值给
$accessToken,但传入setAuthConfig的是未定义变量$access_token,会导致OAuth凭证根本没有被正确加载。其他接口能正常响应是因为配置了simple_api_key可以走公开数据访问逻辑,但Captions字幕下载接口不支持仅用API key鉴权,必须携带有效的OAuth2访问令牌。 - 删除重复的token获取逻辑:OAuth授权码(auth code)是一次性凭证,代码中先后两次调用
fetchAccessTokenWithAuthCode,第二次调用时授权码已经失效,必然返回鉴权错误,只保留第一次token获取逻辑即可。 - 确认接口权限规则:Captions接口仅支持下载当前授权账号所属频道下的视频字幕,无法通过该接口下载其他用户公开/未公开视频的字幕。如果目标视频不属于当前授权账号,哪怕scope配置正确也会返回403权限错误,这类公开视频的字幕可以直接通过前端字幕地址获取,不需要走Data API。
- 移除冲突的鉴权配置:
setDeveloperKey配置的API密钥用于公开无用户态的接口访问,和OAuth用户授权令牌同时传入时会触发鉴权逻辑冲突,调用需要用户授权的Captions接口时删掉$client->setDeveloperKey($simple_api_key);这行配置即可,非必要的youtubepartner权限范围也可以一并移除,减少不必要的鉴权校验。 - 避免手动配置HTTP请求:检查Google_Client初始化后生成的授权Guzzle客户端是否配置了
base_uri为https://www.googleapis.com,如果缺失该配置,请求时写的相对路径/youtube/v3/captions/xxx会被转发到错误地址,直接使用官方SDK封装的$youtube->captions->download()方法发起请求可以避免这类路径配置错误。 - 校验参数合法性:如果请求中
tlang指定的翻译语言在对应字幕轨道中不存在,也会返回错误,先调用captions.list接口查询对应视频可用的字幕轨道和支持的翻译语言,再传入合法参数发起下载请求。
修正后核心代码参考
$client = new Google_Client(); $client->setApplicationName('My First Project'); $client->setClientId(get_option('gapi_client_id')); $client->setClientSecret(get_option('gapi_client_secret')); $client->setRedirectUri('https://income.tube/wp-admin/admin.php?page=rnd-eytes'); $client->setScopes([ 'https://www.googleapis.com/auth/youtube.force-ssl', 'https://www.googleapis.com/auth/youtube.readonly' ]); $client->setAccessType('offline'); $authCode = get_option('gapi_auth_code'); $accessToken = $client->fetchAccessTokenWithAuthCode($authCode); $client->setAccessToken($accessToken); // 直接用官方SDK封装的服务类,避免手动写HTTP请求的配置错误 $youtube = new Google_Service_YouTube($client); $params = [ 'tfmt' => 'vtt', 'tlang' => 'fr' ]; $response = $youtube->captions->download('OdIfTQmbuCS8lIzTWpQoHP66BOQh1VfTCmNAH-qo6vE=', $params); file_put_contents(__DIR__ . '/Libs/caption.vtt', $response->getBody()->getContents());
内容的提问来源于stack exchange,提问作者Sarbjit Singh
相关产品推荐
相关产品推荐

