Youtube Player Api获取屏幕截图

问题描述 投票:0回答:1

iframe上有一个this page,我想从video标签中获取屏幕截图,所以我必须到达iframe标签中的视频标签。

当我打开控制台并运行此代码时:

 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 Player API获取屏幕截图?

javascript iframe youtube-api youtube-javascript-api youtube-iframe-api
1个回答
0
投票

据我所知,由于它基于iFrame,因此无法从YouTube Player API中截取屏幕截图。如果您想在自己的应用程序中(而不只是浏览器扩展程序)制作它们,CORS将禁止执行此操作(导致异常的原因)。

唯一的解决方法是使用YouTube视频作为源,使用可以从YouTube获取的数据作为视频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/

基于expressjs服务器的概念证明简单Web应用程序:https://github.com/RinSer/YouCut

© www.soinside.com 2019 - 2024. All rights reserved.