如何通过YouTube API v3为视频添加字幕?(无客户端库实现)
YouTube API v3 上传字幕的正确请求格式及多语言实现
你遇到的错误核心原因是:上传字幕需要同时提交元数据和字幕文件内容,不能用application/json的单一格式,必须使用multipart/form-data类型的请求,把元数据和文件分两部分传递。
正确的请求核心结构
- HTTP方法:POST
- 请求URL:
https://youtube.googleapis.com/youtube/v3/captions?part=id,snippet - Content-Type:
multipart/form-data - 请求包含两个关键部分:
snippet:JSON格式的元数据(语言、字幕名称、目标视频ID等)file:字幕文件的二进制内容(支持.srt、.vtt等常见字幕格式)
各语言无客户端库实现
Node.js(纯http模块)
const http = require('http'); const fs = require('fs'); const boundary = '----' + Date.now().toString(16); // 替换为你的实际参数 const apiKey = 'YOUR_API_KEY'; const videoId = 'r6RMj7Y-NwL'; const captionFilePath = './subtitles.srt'; // 构建元数据 const metadata = JSON.stringify({ snippet: { language: 'en', name: 'Test', videoId: videoId } }); // 读取字幕文件 const fileContent = fs.readFileSync(captionFilePath); // 组装multipart表单数据 const bodyParts = [ `--${boundary}`, 'Content-Disposition: form-data; name="snippet"', 'Content-Type: application/json', '', metadata, `--${boundary}`, `Content-Disposition: form-data; name="file"; filename="${captionFilePath.split('/').pop()}"`, 'Content-Type: application/x-subrip', // .vtt格式替换为text/vtt '', fileContent, `--${boundary}--` ]; // 转换为Buffer const body = Buffer.concat(bodyParts.map(part => typeof part === 'string' ? Buffer.from(part + '\r\n') : part )); // 配置请求选项 const options = { hostname: 'youtube.googleapis.com', path: `/youtube/v3/captions?part=id,snippet&key=${apiKey}`, method: 'POST', headers: { 'Content-Type': `multipart/form-data; boundary=${boundary}`, 'Content-Length': body.length } }; // 发送请求并处理响应 const req = http.request(options, (res) => { let data = ''; res.on('data', (chunk) => data += chunk); res.on('end', () => console.log(JSON.parse(data))); }); req.on('error', (err) => console.error(err)); req.write(body); req.end();
Curl命令
# 替换为你的实际参数 curl -X POST \ "https://youtube.googleapis.com/youtube/v3/captions?part=id,snippet&key=YOUR_API_KEY" \ -H "Content-Type: multipart/form-data" \ -F "snippet={\"language\":\"en\",\"name\":\"Test\",\"videoId\":\"r6RMj7Y-NwL\"}" \ -F "file=@./subtitles.srt;type=application/x-subrip"
Java(纯HttpURLConnection)
import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; public class UploadYoutubeCaption { public static void main(String[] args) throws IOException { // 替换为你的实际参数 String apiKey = "YOUR_API_KEY"; String videoId = "r6RMj7Y-NwL"; String captionFilePath = "./subtitles.srt"; String boundary = "----" + System.currentTimeMillis(); URL url = new URL("https://youtube.googleapis.com/youtube/v3/captions?part=id,snippet&key=" + apiKey); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); try (OutputStream os = conn.getOutputStream(); PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8), true); FileInputStream fis = new FileInputStream(captionFilePath)) { // 写入元数据部分 writer.append("--").append(boundary).append("\r\n"); writer.append("Content-Disposition: form-data; name=\"snippet\"").append("\r\n"); writer.append("Content-Type: application/json").append("\r\n"); writer.append("\r\n"); writer.append("{\"snippet\":{\"language\":\"en\",\"name\":\"Test\",\"videoId\":\"").append(videoId).append("\"}}").append("\r\n"); // 写入字幕文件部分 writer.append("--").append(boundary).append("\r\n"); writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(new File(captionFilePath).getName()).append("\"").append("\r\n"); writer.append("Content-Type: application/x-subrip").append("\r\n"); // .vtt替换为text/vtt writer.append("\r\n"); writer.flush(); // 写入文件二进制内容 byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = fis.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } os.flush(); // 结束表单边界 writer.append("\r\n").append("--").append(boundary).append("--").append("\r\n"); writer.flush(); } // 读取并打印响应 try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } finally { conn.disconnect(); } } }
PHP(纯curl扩展)
<?php // 替换为你的实际参数 $apiKey = 'YOUR_API_KEY'; $videoId = 'r6RMj7Y-NwL'; $captionFilePath = './subtitles.srt'; $url = "https://youtube.googleapis.com/youtube/v3/captions?part=id,snippet&key={$apiKey}"; // 构建POST数据,包含元数据和文件 $postData = [ 'snippet' => json_encode([ 'language' => 'en', 'name' => 'Test', 'videoId' => $videoId ]), 'file' => new CURLFile($captionFilePath, 'application/x-subrip', basename($captionFilePath)) ]; // 初始化curl请求 $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 执行请求并处理响应 $response = curl_exec($ch); if (curl_errno($ch)) { echo '请求错误: ' . curl_error($ch); } else { print_r(json_decode($response, true)); } curl_close($ch); ?>
内容的提问来源于stack exchange,提问作者Mykyta Manuilenko
相关产品推荐
相关产品推荐

