You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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
  • 请求包含两个关键部分:
    1. snippet:JSON格式的元数据(语言、字幕名称、目标视频ID等)
    2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 13:20:28