在电子中播放本地mp4文件

Umu*_*zer 6 macos html5-video electron

我正在尝试开发一个小应用程序,我首先通过aperture包捕获屏幕,然后尝试使用video标记在屏幕上显示它.

我捕获屏幕:

import apertureConstructor from 'aperture';
const aperture = apertureConstructor();

const options = {
  fps: 30
};

(async () => {
  await aperture.startRecording(options);
  setTimeout(async () => {
    this.captureUrl = await aperture.stopRecording();
  }, 3000)
})();
Run Code Online (Sandbox Code Playgroud)

请忽略这个烂摊子.Aperture包将捕获的视频写入磁盘,最终,我有了这个文件的路径captureUrl.它是这样的:

/var/folders/29/08gshk3n4mlbbcjnm1m5xyy40000gp/T/tmp-79999m0uOszQK0zaC.mp4

我可以验证此文件是否存在并且播放正常,如果我输入:file:///var/folders/29/08gshk3n4mlbbcjnm1m5xyy40000gp/T/tmp-79999m0uOszQK0zaC.mp4到Google Chrome地址栏.

所以我尝试使用这个地址作为我的video标签的来源,如下所示:

 <video control autoplay>
   <source src="/var/folders/29/08gshk3n4mlbbcjnm1m5xyy40000gp/T/tmp-8004145a2o4gugbVV.mp4" type="video/mp4">
 </video>
Run Code Online (Sandbox Code Playgroud)

哪个抱怨该文件不存在(404):

GET http://localhost:9080/var/folders/29/08gshk3n4mlbbcjnm1m5xyy40000gp/T/tmp-8004145a2o4gugbVV.mp4 404 (Not Found)
Run Code Online (Sandbox Code Playgroud)

是的,它确实试图去,localhost:9080因为在这种情况下它是我的开发服务器主机,并没有这样的文件.

所以我决定添加file://......

<video controls autoplay>
  <source src="file:///var/folders/29/08gshk3n4mlbbcjnm1m5xyy40000gp/T/tmp-8004145a2o4gugbVV.mp4" type="video/mp4">
</video>
Run Code Online (Sandbox Code Playgroud)

这次它说:

Not allowed to load local resource: file:///var/folders/29/08gshk3n4mlbbcjnm1m5xyy40000gp/T/tmp-80041e3SlBZUNphLM.mp4
Run Code Online (Sandbox Code Playgroud)

:/

我想知道我是否错过了使"file://"安全或其他东西的东西.

我还考虑过通过"fs"读取整个文件,并考虑提供视频,data:但由于这个视频文件可能很大,我觉得我不应该这样做.

因为我是新手,electron我希望我会错过一些基本的东西.任何帮助表示赞赏.谢谢!

tch*_*har 11

由于已经有一个公认的答案,我只会告诉你我是如何为可能遇到同样问题的人解决这个问题的。

这时候有一种方法可以通过使用protocol来做到这一点,即使你指定

webPreferences: {
  webSecurity: true,
}
Run Code Online (Sandbox Code Playgroud)

通常要显示图像或播放文件中的视频,您会执行以下操作

<video controls autoplay>
  <source src="file:///path-to-video.mp4">
</video>
Run Code Online (Sandbox Code Playgroud)

但这不适用于 webpack,因为 webpack 会生成一个服务器,并且默认情况下,file://出于安全原因,不会加载以 开头的所有内容。如果电子加载了,file://index.html那么它可能会工作,但协议方式非常酷,您可以保护您的资源。

要解决您的问题,您可以执行以下操作:

const { protocol } = require('electron');

function fileHandler(req, callback){
  let requestedPath = req.url
  // Write some code to resolve path, calculate absolute path etc
  let check = // Write some code here to check if you should return the file to renderer process

  if (!check){
    callback({
      // -6 is FILE_NOT_FOUND
      // https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h
      error: -6 
    });
    return;
  }

  callback({
    path: requestedPath
  });
}

// Then in electron main.js

app.on("ready", () => {
  
  protocol.registerFileProtocol(
    'your-custom-protocol',
    fileHandler,
  );

  // Create some window you can even use webPreferences: true
});
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样在你的html代码中使用它

<video controls autoplay>
  <source src="your-custom-protocol:///path-to-video.mp4">
</video>

Run Code Online (Sandbox Code Playgroud)

通过这样做,您可以确保您的应用程序是安全的,并且它不会从文件系统请求随机文件,并且它也可以很好地与 webpack 配合使用。

有关此内容的更多信息,有一个 github 存储库来展示电子中的安全模式。看看这里


Ali*_*RIN 4

尽管我不喜欢鼓励这样做,但为了解决问题,我建议您在 BrowserWindow 中禁用 Web 安全首选项。另外,还有一个与该主题相关的问题。