使用YouTube Data API v3下载字幕遇401未授权问题求助
首先得明确:虽然网页播放器能免费查看字幕,但YouTube Data API对字幕下载的权限要求和前端播放器完全不同,这就是你遇到401错误的核心原因。
为什么只用API Key不行?
- API Key仅适用于无需用户身份验证的公开数据读取操作(比如获取视频标题、搜索视频),但字幕属于受版权保护的内容——哪怕是自动生成的字幕,YouTube也要求下载操作必须通过OAuth 2.0授权来验证用户身份,确保你有合法的访问权限(比如你是视频所有者,或者视频允许观众下载字幕)。
- 网页播放器的“Open transcript”是YouTube提供的前端服务,它的权限验证逻辑是内部处理的,不需要用户手动授权就能查看,但API遵循更严格的开发者权限规范,必须明确验证用户身份。
解决方案:实现OAuth 2.0授权流程
你需要修改代码,用OAuth 2.0凭据代替单纯的API Key。具体步骤如下:
在Google Cloud Console创建OAuth客户端凭据:
- 进入你的项目,找到“API和服务”→“凭据”,创建“OAuth客户端ID”,类型选择“桌面应用”。
- 下载生成的
credentials.json文件,放在你的项目路径下。
修改Java代码,加入OAuth授权逻辑:
下面是完整的可运行代码示例,替换你的视频ID即可:
import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.gson.GsonFactory; import com.google.api.client.util.store.FileDataStoreFactory; import com.google.api.services.youtube.YouTube; import com.google.api.services.youtube.model.Caption; import com.google.api.services.youtube.model.CaptionListResponse; import com.google.api.services.youtube.model.CaptionSnippet; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.FileOutputStream; import java.security.GeneralSecurityException; import java.util.Collections; import java.util.List; public class YouTubeCaptionDownloader { private static final String APPLICATION_NAME = "YouTube Caption Downloader"; private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance(); private static final String TOKENS_DIRECTORY_PATH = "tokens"; // 下载字幕所需的权限范围 private static final List<String> SCOPES = Collections.singletonList("https://www.googleapis.com/auth/youtube.force-ssl"); private static final String CREDENTIALS_FILE_PATH = "credentials.json"; // 注意路径要正确 private static Credential getCredentials(final com.google.api.client.http.HttpTransport HTTP_TRANSPORT) throws IOException { // 加载客户端密钥文件 FileInputStream in = new FileInputStream(new File(CREDENTIALS_FILE_PATH)); GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in)); // 创建授权流,保存令牌到本地 GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES) .setDataStoreFactory(new FileDataStoreFactory(new File(TOKENS_DIRECTORY_PATH))) .setAccessType("offline") // 允许离线访问,后续无需重复授权 .build(); LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build(); return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user"); } public static void main(String[] args) throws GeneralSecurityException, IOException { // 初始化HTTP传输和YouTube服务(带OAuth授权) final com.google.api.client.http.HttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); YouTube youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT)) .setApplicationName(APPLICATION_NAME) .build(); String videoId = "YOUR_TARGET_VIDEO_ID"; // 替换成你要下载字幕的视频ID // 请求该视频的字幕列表 YouTube.Captions.List request = youtube.captions().list("snippet", videoId); CaptionListResponse response = request.execute(); List<Caption> captions = response.getItems(); for (Caption caption : captions) { CaptionSnippet snippet = caption.getSnippet(); System.out.println("===== 字幕信息 ====="); System.out.println("ID: " + caption.getId()); System.out.println("名称: " + snippet.getName()); System.out.println("语言: " + snippet.getLanguage()); String captionID = caption.getId(); String outputFileName = "captions_" + captionID + ".vtt"; // 下载并保存字幕到本地文件 try (OutputStream output = new FileOutputStream(outputFileName)) { YouTube.Captions.Download downloadReq = youtube.captions().download(captionID); downloadReq.executeMediaAndDownloadTo(output); System.out.println("字幕已成功保存到:" + outputFileName); } catch (IOException e) { System.err.println("下载字幕失败:" + e.getMessage()); } } } }
额外注意事项
- 确保你已经在Google Cloud Console中启用了YouTube Data API v3,否则会提示API未启用的错误。
- 第一次运行代码时,会自动打开浏览器让你登录Google账号,授权应用访问你的YouTube数据。授权成功后,令牌会保存在
tokens目录下,后续运行不需要再次授权。 - 不是所有公开视频的字幕都允许下载:如果视频所有者在后台禁用了字幕下载权限,即使你完成了OAuth授权,也会收到
403 Forbidden错误,这属于视频所有者的权限设置问题,无法通过代码解决。
内容的提问来源于stack exchange,提问作者Daniel




