代码之家  ›  专栏  ›  技术社区  ›  Muhammed Ozdogan

Youtube播放器Api获取屏幕截图

  •  0
  • Muhammed Ozdogan  · 技术社区  · 5 年前

    有一个 iframe this page 我想从 video

     const videoElement = document.getElementsByTagName('iframe')[0]
                     .contentWindow.document.getElementsByTagName('video')[0];
    
    //Extracting picture from video tag
        const canvas = document.createElement('canvas');
            canvas.width = videoElement.videoWidth;
            canvas.height = videoElement.videoHeight;
            canvas.getContext('2d').drawImage(videoElement, 0, 0, canvas.width, canvas.height);
    

    已引发此错误:

    Uncaught DOMException: Blocked a frame with origin "https://developers.google.com" from accessing a cross-origin frame.
        at <anonymous>:1:57
    

    另外,我查过了 this

    我的问题是如何从YouTube播放器API获取截图?

    0 回复  |  直到 5 年前
        1
  •  3
  •   Serj DuKareff    5 年前

    据我所知,没有办法从YouTube播放器API截图,因为它是基于iFrame的。如果你想在你自己的应用程序(不仅仅是一个浏览器扩展),这个操作将被CORS禁止(这是你得到异常的原因)。

    唯一的解决办法是使用可以从YouTube获取的数据将YouTube视频作为源放入video HTML元素中。 此代码应便于获取视频的源URL:

    class YoutubeVideo {
    
        constructor(video_id, callback) {
            return (async () => {
                // You should also redirect those requests
                // through your own API that would permit CORS
                const response = await fetch(`https://www.youtube.com/get_video_info?video_id=${video_id}`, {
                    headers: { 'Content-Type' : 'text/plain'}
                });
                const video_info = await response.text();
                
                let video = this.decodeQueryString(video_info);
                if (video.status === 'fail') {
                    return callback(video);
                }
                
                if (video.url_encoded_fmt_stream_map) 
                    video.source = this.decodeStreamMap(video.url_encoded_fmt_stream_map);
    
                return callback(video);
            })();
        }
    
        decodeQueryString(queryString) {
            var key, keyValPair, keyValPairs, r, val, _i, _len;
            r = {};
            keyValPairs = queryString.split("&");
            for (_i = 0, _len = keyValPairs.length; _i < _len; _i++) {
                keyValPair = keyValPairs[_i];
                key = decodeURIComponent(keyValPair.split("=")[0]);
                val = decodeURIComponent(keyValPair.split("=")[1] || "");
                r[key] = val;
            }
            return r;
        }
    
        decodeStreamMap(url_encoded_fmt_stream_map) {
            var quality, sources, stream, type, urlEncodedStream, _i, _len, _ref;
            sources = {};
            _ref = url_encoded_fmt_stream_map.split(",");
            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                urlEncodedStream = _ref[_i];
                stream = this.decodeQueryString(urlEncodedStream);
                type = stream.type.split(";")[0];
                quality = stream.quality.split(",")[0];
                stream.original_url = stream.url;
                stream.url = "" + stream.url + "&signature=" + stream.sig;
                sources["" + type + " " + quality] = stream;
            }
            return sources;
        }
    }

    在构造函数中传递给回调的对象将具有source属性,该属性包含所有可用视频类型和质量的源链接,您可以在浏览器控制台上更好地检查它们。 尽管如此,并不是所有的YouTube视频都可以这样处理,我遇到了更多的限制文件,当你只能得到禁止的错误或空源。

    https://github.com/endlesshack/youtube-video

    基于此解决方案工作的资源: http://youtubescreenshot.com/

    https://github.com/RinSer/YouCut