YouTube视频不在Electron应用中播放,但在网站中播放

时间:2018-10-17 13:38:53

标签: javascript angularjs angular youtube electron

我正在研究两个相关项目,一个网页和Electron中的一个应用程序,除其他外,两者都必须播放嵌入在iframe中的Youtube视频。一切都能在网站上完美运行,

var newUrl = 'http://www.youtube.com/embed/' + $scope.youtube_parser(video.url);
        $scope.videoURL = $sce.trustAsResourceUrl(newUrl + '?enablejsapi=1&showinfo=0&rel=0');
$scope.setYTPlayer();

$scope.setYTPlayer = function(){
    $scope.player;
    $scope.player = new YT.Player('player', {
        height: '360',
        width: '640',
        videoId: $scope.videoSelected,
        events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
        }
    });
}
<iframe id="player" frameborder="0" allowfullscreen ng-src="{{videoURL}}" style="width: 100%;height: 100%;"></iframe>

但是在Electron应用程序中,许多视频都没有播放,播放器上显示一条消息:“视频不可用”

var youtubeId = $scope.getYoutubeId(video.url)
    $scope.currentVideo = $sce.trustAsResourceUrl(
      'https://www.youtube.com/embed/' + youtubeId + '?rel=0'
    )
<iframe width="100%" height="442" ng-src="{{ currentVideo }}" frameborder="0" allowfullscreen></iframe>

Capture of the player

页面上的相同链接使用相同的方法可以毫无问题地重现。仅尝试通过api使用iframe,更改播放参数,问题仍然存在。 问题是,是否有Youtube政策禁止在某些地方播放视频?或者是什么错误?

电子版本:v3.0.3

如果不能很好地表达自我,谢谢和道歉。

1 个答案:

答案 0 :(得分:2)

出现此问题的原因是打开电子窗口所依据的协议。 如果打开本地html文件,则使用“ file://”协议。我找到了2个解决此问题的方法:

您可以引发本地临时http服务器,以传输窗口的html文件,然后将其禁用。

import http from 'http';
import fs from 'fs';
import path from 'path';

//at start
let server;
server = http.createServer((req, res) => {
const filePath = path.join(app.getAppPath(), 'public', req.url);
const file = fs.readFileSync(filePath);
res.end(file.toString());
if (req.url.includes('index.js'))
   server.close();
}).listen(8080);

//after app-ready event
mainWindow.loadURL('http://localhost/index.html');

一个更可取的选择是拦截HTTP协议并传输文件,但是必须在传输所有本地文件后禁用拦截,否则会影响所有后续的HTTP请求。

import path from 'path';

//before window.loadURL
session.defaultSession.protocol.interceptFileProtocol('http', (request, callback) => {
    const fileUrl = request.url.replace('http://localhost/', '');
    const filePath = path.join(app.getAppPath(), 'public', fileUrl);

    if(request.url.includes('index.js')) {
        session.defaultSession.protocol.uninterceptProtocol('http');
    }
    callback(filePath);
});
//after app-ready event
mainWindow.loadURL('http://localhost/index.html');

此外,如果标题“ x-frame-options” =“ sameorigin”出错,则可以在收到响应后删除此标题。

const filter = {
    urls: ['https://www.youtube.com/*']
};
session.defaultSession.webRequest.onHeadersReceived(filter, (details, callback) => {
    for (const header in details.responseHeaders) {
        if (header.toLocaleLowerCase() === 'x-frame-options') {
            delete details.responseHeaders[header];
        }
    }
    callback({ cancel: false, responseHeaders: details.responseHeaders });
});