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

如何使用JavaScript实现YouTube字幕下载功能?

实现Web端JavaScript下载YouTube视频字幕的方案

1. 获取可用字幕列表

通过解析YouTube视频页面的配置数据提取字幕轨道信息,注意浏览器同源策略限制,需通过代理转发请求。

async function getAvailableCaptions(videoId) {
  try {
    // 替换为你的代理地址,规避CORS问题
    const proxyUrl = 'http://localhost:3000/proxy?url=';
    const targetUrl = `https://www.youtube.com/watch?v=${videoId}&hl=en&has_verified=1&bpctr=9999999999`;
    const response = await fetch(proxyUrl + encodeURIComponent(targetUrl));
    const html = await response.text();

    const captionMatch = html.match(/ytplayer\.config\s*=\s*({.*?});/);
    if (!captionMatch) throw new Error('无法提取字幕配置');

    const config = JSON.parse(captionMatch[1]);
    const captionTracks = config.args.player_response.captions?.playerCaptionsTracklistRenderer?.captionTracks || [];

    return captionTracks.map(track => ({
      label: track.name.simpleText,
      languageCode: track.languageCode,
      baseUrl: track.baseUrl
    }));
  } catch (err) {
    console.error('获取字幕列表失败:', err);
    return [];
  }
}

2. 渲染语言选择器

动态生成下拉菜单供用户选择目标字幕语言:

<input type="text" id="videoIdInput" placeholder="输入YouTube视频ID">
<button onclick="loadCaptions()">加载字幕选项</button>
<select id="languageSelect"></select>
<button onclick="downloadSelectedCaption()">下载SRT字幕</button>
async function loadCaptions() {
  const videoId = document.getElementById('videoIdInput').value.trim();
  if (!videoId) {
    alert('请输入视频ID');
    return;
  }

  const captions = await getAvailableCaptions(videoId);
  const select = document.getElementById('languageSelect');
  select.innerHTML = '';

  captions.forEach(caption => {
    const option = document.createElement('option');
    option.value = caption.baseUrl;
    option.textContent = `${caption.label} (${caption.languageCode})`;
    select.appendChild(option);
  });
}

3. 转换字幕为SRT格式

请求字幕XML数据并解析转换为标准SRT格式:

async function fetchAndConvertToSrt(captionUrl) {
  const proxyUrl = 'http://localhost:3000/proxy?url=';
  const targetUrl = `${captionUrl}&fmt=srv3`; // fmt参数指定返回兼容SRT的XML格式
  const response = await fetch(proxyUrl + encodeURIComponent(targetUrl));
  const xmlText = await response.text();
  const xmlDoc = new DOMParser().parseFromString(xmlText, 'text/xml');

  const cues = xmlDoc.getElementsByTagName('text');
  let srtContent = '';
  let index = 1;

  for (const cue of cues) {
    const start = parseFloat(cue.getAttribute('start'));
    const duration = parseFloat(cue.getAttribute('dur'));
    const end = start + duration;

    const text = cue.textContent.replace(/\n+/g, ' ').trim();
    if (!text) continue;

    srtContent += `${index}\n${formatSrtTime(start)} --> ${formatSrtTime(end)}\n${text}\n\n`;
    index++;
  }

  return srtContent;
}

// 将秒数转换为SRT时间格式:00:00:00,000
function formatSrtTime(seconds) {
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const secs = seconds % 60;

  return [
    String(hours).padStart(2, '0'),
    String(minutes).padStart(2, '0'),
    secs.toFixed(3).padStart(6, '0').replace('.', ',')
  ].join(':');
}

4. 触发浏览器下载

生成Blob对象并通过a标签触发下载:

async function downloadSelectedCaption() {
  const select = document.getElementById('languageSelect');
  const selectedUrl = select.value;
  if (!selectedUrl) {
    alert('请选择字幕语言');
    return;
  }

  try {
    const srtContent = await fetchAndConvertToSrt(selectedUrl);
    const blob = new Blob([srtContent], { type: 'application/x-subrip' });
    const url = URL.createObjectURL(blob);

    const a = document.createElement('a');
    a.href = url;
    a.download = 'youtube-subtitle.srt';
    document.body.appendChild(a);
    a.click();

    URL.revokeObjectURL(url);
    document.body.removeChild(a);
  } catch (err) {
    console.error('下载失败:', err);
    alert('字幕下载失败,请检查视频ID或代理配置');
  }
}

关键注意事项

  • CORS代理:浏览器禁止直接跨域请求YouTube,必须搭建代理服务器转发请求。以下是简单的Node.js代理示例:
const express = require('express');
const fetch = require('node-fetch');
const app = express();

app.get('/proxy', async (req, res) => {
  const url = decodeURIComponent(req.query.url);
  try {
    const response = await fetch(url);
    const data = await response.text();
    res.set('Content-Type', response.headers.get('Content-Type'));
    res.send(data);
  } catch (err) {
    res.status(500).send('代理请求失败');
  }
});

app.listen(3000, () => console.log('代理服务器运行在 http://localhost:3000'));
  • API替代方案:如果需要更高稳定性,可使用YouTube Data API v3的captions.list接口获取字幕,但需API密钥,且有请求配额限制。
  • 字幕格式适配:部分视频的字幕XML结构可能不同,需根据实际返回的标签调整解析逻辑(比如有的用<p>标签替代<text>)。

内容的提问来源于stack exchange,提问作者Rebaz Xoshnaw

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 00:04:54