据我所知,没有办法从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