获取YouTube字幕

时间:2015-08-21 14:17:25

标签: javascript java video youtube-api video.js

如何以编程方式获取正在播放的YouTube视频的字幕?

最初我尝试通过YouTube API离线进行,但as it seems YouTube禁止提取您不是所有者的视频字幕。

现在我正在尝试在线进行。我还没有找到YouTube Player Api字幕的方法,我也试图在videojs中使用the way it could be done for usual videos播放器将YouTube字幕设为TextTrack,但以下内容不起作用:

<html>
<head>
<link href="//vjs.zencdn.net/4.12/video-js.css" rel="stylesheet">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript" src="//vjs.zencdn.net/4.12/video.js"></script>
<script type="text/javascript" src="../lib/youtube.js"></script>
</head>

<body>
<video  id="myvideo"
        class="video-js vjs-default-skin vjs-big-play-centered" 
        controls 
        preload="auto" 
        width="640" 
        height="360">
</video>

<script type="text/javascript">
    var myvideo = videojs(
        "myvideo",
        {
            "techOrder": ["youtube"],
            "src": "https://www.youtube.com/watch?v=jNhtbmXzIaM" 
        },
        function() {
            console.log('Tracks: ' + this.textTracks().length); //zero here :(

            /*var aTextTrack = this.textTracks()[0];
            aTextTrack.on('loaded', function() {
                console.log('here it is');
                cues = aTextTrack.cues();
                console.log('Ready State', aTextTrack.readyState()) 
                console.log('Cues', cues);
            });
            aTextTrack.show();*/
        });
</script>
</body>
</html>

我还尝试过解析YouTube播放器IFrame的丑陋解决方案(里面有一个带有当前字幕行的div),但由于原因不匹配的安全问题,它无效。

有没有办法可以在java(离线解决方案)或javascript(在线解决方案)中实现我的目标?

4 个答案:

答案 0 :(得分:5)

我是如何设法从YouTube视频获取字幕的,只需向此网址发出简单请求https://video.google.com/timedtext?lang= {LANG}&amp; v = {videoId}

我曾尝试使用Youtube API v3但目前它不起作用。当您使用Youtube API v3对特定视频发出请求时,您需要上传视频的人批准标题的下载,否则您将在控制台中出现403错误。发生错误是正常的,服务器没有收到批准,因此它返回错误。

您可以使用Youtube API v3从自己的视频下载字幕。

类似的东西可以完成这项工作。响应将采用XML格式:

   $.ajax({
        type: "POST",
        url: "https://video.google.com/timedtext?lang=en&v=5MgBikgcWnY"
    }).done(function (response) {
        console.log(response);
    }).fail(function (response) {
        console.log();
    });

答案 1 :(得分:0)

您可能不需要直接从YouTube下载它,您可以操作Web服务。

例如,您可以在此处转到http://keepsubs.com/?url=insert_youtube_url,并通过此CSS路径中的链接从网站下载字幕,以获取英文字幕:

#dl > a:nth-child(2)

您可以使用以下方法在javascript中执行此操作:

function myFunction(url_to_download){
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", "http://keepsubs.com/?url=" + url_to_download, false );
    xmlHttp.send( null );
    var fake_html = document.createElement("div");
    fake_html.insertAdjacentHTML('beforeend', xmlHttp.responseText);
    var url = fake_html.querySelector("#dl > a:nth-child(2)");

    xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", url.href, false );
    xmlHttp.send( null );

    console.log(xmlHttp.responseText);
    return xmlHttp.responseText;
    }
myFunction("https://www.youtube.com/watch?v=dQw4w9WgXcQ");

基本上,此方法访问KeepSubs,找到文本下载URL,获取文件中的文本,并将其输出到控制台。

请记住,虽然这是一种方法,但可能更好的方法不是那么黑客。同样使用KeepSubs服务这种方式可能不符合道德标准。但这仅用于教育目的。

答案 2 :(得分:0)

基于Sergiu Mare的建议,我编写了一个封装的函数,该函数可以在控制台中返回字幕。

这是用纯JavaScript(ES6)编写的,您可以在下面进行测试,也可以复制下面的所有内容并将其粘贴到任何带字幕的视频的控制台中。

loadYouTubeSubtitles((getYouTubeVideoId() || 'fJ9rUzIMcZQ'), {
  callbackFn : function(json) {
    console.log(jsonToCsv(json, {
      includeHeader : false,
      ignoreKeys : [ 'dur' ],
      delimiter : '\t',
    }));
  }
}); // Queen – Bohemian Rhapsody (default ID)

function getYouTubeVideoId() {
  var video_id = window.location.search.split('v=')[1];
  if (video_id != null) {
    var ampersandPosition = video_id.indexOf('&');
    if (ampersandPosition != -1) {
      return video_id.substring(0, ampersandPosition);
    }
  }
  return null;
}

function loadYouTubeSubtitles(videoId, options) {
  options = Object.assign({
    baseUrl : 'https://video.google.com/timedtext',
    languageId : 'en',
    callbackFn : function(json) { console.log(json); } // Default
  }, options || {});

  // https://stackoverflow.com/a/9609450/1762224
  var decodeHTML = (function() {
    let el = document.createElement('div');
    function __decode(str) {
      if (str && typeof str === 'string') {
        str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '')
          .replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');
        el.innerHTML = str;
        str = el.textContent;
        el.textContent = '';
      }
      return str;
    }
    removeElement(el); // Clean-up
    return __decode;
  })();
  
  function removeElement(el) {
    el && el.parentNode && el.parentNode.removeChild(el);
  }

  function parseTranscriptAsJSON(xml) {
    return [].slice.call(xml.querySelectorAll('transcript text'))
      .map(text => ({
        start : formatTime(Math.floor(text.getAttribute('start'))),
        dur : formatTime(Math.floor(text.getAttribute('dur'))),
        text : decodeHTML(text.textContent).replace(/\s+/g, ' ')
      }));
  }

  function formatTime(seconds) {
    let date = new Date(null);
    date.setSeconds(seconds);
    return date.toISOString().substr(11, 8);
  }

  let xhr = new XMLHttpRequest();
  xhr.open('POST', `${options.baseUrl}?lang=${options.languageId}&v=${videoId}`, true);
  xhr.responseType = 'document';
  xhr.onload = function() {
    if (this.status >= 200 && this.status < 400) {
      options.callbackFn(parseTranscriptAsJSON(this.response));
    } else {
      console.log('Error: ' + this.status);
    }
  };
  xhr.onerror = function() {
    console.log('Error!');
  };
  xhr.send();
}

function jsonToCsv(json, options) {
  options = Object.assign({
    includeHeader : true,
    delimiter : ',',
    ignoreKeys : []
  }, options || {});
  let keys = Object.keys(json[0]).filter(key => options.ignoreKeys.indexOf(key) === -1);
  let lines = [];
  if (options.includeHeader) { lines.push(keys.join(options.delimiter)); }
  return lines.concat(json
    .map(entry => keys.map(key => entry[key]).join(options.delimiter)))
    .join('\n');
}
.as-console-wrapper { top: 0; max-height: 100% !important; }

答案 3 :(得分:0)

首先,如果是您的视频,您一定要尝试使用官方 API! 其次,您应该尝试在此处查看数据是否可用:https://video.google.com/timedtext?lang={LANG}&v={videoId}

现在,如果您想要第三种方法,并且您感兴趣的是获取 ASR 标题(ASR = 自动语音识别),那么还有另一种方法可以通过抓取 youtube get_video_info 数据。

为了做到这一点,您需要:

第 1 步。为您的 videoID 获取 get_video_info 文件。这里https://youtube.com/get_video_info?video_id=videoID

第 2 步。在此数据中,您将找到 captionTracks > baseURL

step3. 只需复制 baseURL 链接,您就可以看到 ASR xml 数据(如果视频支持)。

如果您使用 nodejs,有一种简单的方法可以通过编程来实现:

npm i ytgetcaption
caption = require('ytgetcaption');

VideoID = "1RhRRRG6MBU"

caption.ytgetCaption(VideoID).then(function (data) {
    console.log(data)
});

https://www.npmjs.com/package/ytgetcaption