最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Youtube Player Api Get Screenshot - Stack Overflow

programmeradmin1浏览0评论

There is an iframe on this page I want to get a screenshot from the video tag, so I have to reach video tag that in the iframe tag.

When I open the console and run this code:

 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);

This error has been thrown:

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

Also, I checked this question

My question is how can I get a screenshot from YouTube Player API?

There is an iframe on this page I want to get a screenshot from the video tag, so I have to reach video tag that in the iframe tag.

When I open the console and run this code:

 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);

This error has been thrown:

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

Also, I checked this question

My question is how can I get a screenshot from YouTube Player API?

Share Improve this question asked May 24, 2019 at 22:03 Muhammed OzdoganMuhammed Ozdogan 5,8978 gold badges37 silver badges56 bronze badges 9
  • You say that you checked the question you linked to, but it directly addresses your concern - you cannot interact directly with the content of an iframe that is from a different origin. If you could, that would wreck the security of the internet. Also, why not just use the official API, which allows you to get thumbnails / screenshots? - stackoverflow./a/2108248 – Joshua T Commented May 24, 2019 at 23:08
  • I need to take a screenshot from a specific time lets say video length is 100 second, I would able to take a screenshot at 44'th second. But thumbnails are static – Muhammed Ozdogan Commented May 24, 2019 at 23:40
  • That makes sense, but that doesn't change the fact that you simply can't do with that embeds by themselves (your main question). Your options are basically - A) Download the video and use something like FFMPEG to extract the frame, B) use something like puppeteer to run a headless Chrome and screenshot the video, or C) use a screenshot-api service like URL2PNG and pass it the embed URL as the page to screenshot. – Joshua T Commented May 25, 2019 at 7:14
  • Option A looks perfect apart of downloading the video I think vlc can play youtube video from network stream if I could open vlc from mand line with url parameter time parameter it can produce thumbnails dynamicaly: videosolo./tutorials/download-video-with-vlc.html – Muhammed Ozdogan Commented May 25, 2019 at 9:07
  • @Joshua T Can you check out this question: askubuntu./questions/796575/… I mean vlc can open youtube conections If I could extract the frames as images with vlc it would be great. – Muhammed Ozdogan Commented May 25, 2019 at 9:16
 |  Show 4 more ments

1 Answer 1

Reset to default 10

As far as I could find, there is no way to take Screenshots from YouTube Player API as it is based on iFrame. If you want to make them in your own app (not just a browser extension), this operation will be forbidden by CORS (the cause of of the exception that you get).

The only workaround is to put YouTube video as a source into video HTML element using data that you can obtain from YouTube. This code should be handy to get the source urls for video:

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./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;
    }
}

The object passed to the callback in the constructor would have source property that contains source links for all the available video types and qualities, you can examine them better at your browser's console. Nevertheless, not all YouTube videos can be handled that way, I have met files with further restrictions when all you can get is forbidden error or empty sources.

Resource that helped me to find this solution: https://github./endlesshack/youtube-video

Resource that works based on this solution: http://youtubescreenshot./

Proof of concept simple Web App based on expressjs server: https://github./RinSer/YouCut

发布评论

评论列表(0)

  1. 暂无评论