You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron自定义协议加载本地视频失败:渲染层黑屏求助

Electron自定义协议加载本地视频黑屏问题排查

问题说明

使用Electron开发简易视频展示应用,通过registerSchemesAsPrivileged定义appfile协议加载本地视频时,渲染层显示黑屏,开发者工具无内容输出。控制台未出现文件找不到的错误,但存在沙箱相关报错。

相关代码片段

main.ts

import path from 'path';
import { app, BrowserWindow, shell, ipcMain, protocol, net } from 'electron';
import { autoUpdater } from 'electron-updater';
import log from 'electron-log';
import MenuBuilder from './menu';
import { resolveHtmlPath } from './util';
import fs from 'fs'

protocol.registerSchemesAsPrivileged([
  {
    scheme: 'appfile',
    privileges: {
      standard: true,
      secure: true,
      supportFetchAPI: true,
      bypassCSP: true,
    },
  },
]);

app.whenReady().then(() => {
  protocol.handle('appfile', (request) => {
    // Get the file path from the request url
    const filePath = request.url.replace('appfile://', '');
    // Resolve the file path to the absolute file path
    //const absoluteFilePath = path.resolve(filePath);
    // Fetch the file
    console.log(filePath);
    
    return net.fetch(`file:///${filePath}`);
  });
});

App.tsx

import { MemoryRouter as Router, Routes, Route } from 'react-router-dom';
import icon from '../../assets/icon.svg';
import './App.css';
import { useState, useEffect } from 'react';

function Hello() {
  
  //const [videoSource, setVideoSource] = useState<string | null>(null);

  

  return (
    <body>
      <video id="videoPlayer" width="100%" height="100%" autoPlay muted loop>
      <source src="appfile:///home/user/Desktop/project/videos/video1.mp4" />
    </video>
    
    </body>
  );
}

export default function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Hello />} />
      </Routes>
    </Router>
  );
}

控制台输出

home/user/Desktop/project/videos/video1.mp4
[14091:0823/181240.250752:ERROR:CONSOLE(2)] "Electron sandboxed_renderer.bundle.js script failed to run", source: node:electron/js2c/sandbox_bundle (2)
[14091:0823/181240.250873:ERROR:CONSOLE(2)] "TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator))", source: node:electron/js2c/sandbox_bundle (2)

排查建议

  • 修复React组件结构问题:Hello组件直接返回<body>标签不符合React规范,改为用<div>包裹内容,同时给<source>添加type="video/mp4"属性帮助识别视频格式:

    function Hello() {
      return (
        <div>
          <video id="videoPlayer" width="100%" height="100%" autoPlay muted loop>
            <source src="appfile:///home/user/Desktop/project/videos/video1.mp4" type="video/mp4" />
          </video>
        </div>
      );
    }
    
  • 添加协议处理的错误捕获:给protocol.handle添加异步错误捕获,确认文件读取是否存在未被捕获的异常:

    app.whenReady().then(() => {
      protocol.handle('appfile', async (request) => {
        const filePath = request.url.replace('appfile://', '');
        console.log(filePath);
        try {
          const response = await net.fetch(`file:///${filePath}`);
          console.log('文件读取状态:', response.status);
          return response;
        } catch (err) {
          console.error('文件读取错误:', err);
          return new Response('文件未找到', { status: 404 });
        }
      });
    });
    
  • 检查渲染进程沙箱配置:控制台的沙箱报错可能导致协议无法正常工作,临时关闭BrowserWindow的沙箱功能测试(生产环境不推荐,仅用于排查):

    // 在创建BrowserWindow的代码中添加
    const mainWindow = new BrowserWindow({
      webPreferences: {
        sandbox: false,
        // 其他原有配置
      }
    });
    
  • 验证文件路径与权限:确保/home/user/Desktop/project/videos/video1.mp4路径正确,且Electron进程拥有该文件的读取权限。可在main.ts中用fs.access验证:

    fs.access('/home/user/Desktop/project/videos/video1.mp4', fs.constants.R_OK, (err) => {
      if (err) console.error('文件无读取权限:', err);
      else console.log('文件可正常读取');
    });
    

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 09:28:11