electron播放本地任意格式的视频

罗鸿畴
2023-12-01

说明

不支持快进和显示时间,最大流畅支持2G/小时的视频,未使用硬件加速(技术水平不足),高清视频转码太慢。
electron可以直接读取硬盘上的文件,对于mp4视频不需要转码(很不严谨,如需要更严谨,请参考别人的博客),直接将其路径赋值给video的src属性即可;对于非mp4视频,则开启http推流。

npm依赖

"dependencies": {
    "@ffmpeg-installer/ffmpeg": "1.0.20",
    "fluent-ffmpeg": "2.1.2",
    "express": "^4.17.1"
  }

核心代码

创建一个独立的video-server.js文件,在子里程中运行,开启http服务

(function () {
    'use strict';
    const express = require('express');

    const fs = require('fs');

    const app = express();
    const ffmpegPath = require('@ffmpeg-installer/ffmpeg').path;
    const ffmpeg = require('fluent-ffmpeg');
    ffmpeg.setFfmpegPath(ffmpegPath);

    let ffmpegCommand = null;

    app.get('/video', function (req, res) {
        let pathSrc = req.query.video;
        let stat = fs.statSync(pathSrc);
        if (ffmpegCommand !== null) {
            ffmpegCommand.kill();
            ffmpegCommand = null;
        }
        ffmpegCommand = ffmpeg(pathSrc)
            .input(pathSrc)
            .nativeFramerate()
            .videoCodec('libx264')
            .audioCodec('aac')
            .format('mp4')
            .seekInput(0)
            .outputOptions(
                '-movflags', 'frag_keyframe+empty_moov+faststart',
                '-preset', 'veryfast', //以损失画质换取流畅度
                '-g', '18')
            .on('progress', function (progress) {
                console.log('time: ' + progress.timemark);
            })
            .on('error', function (err) {
                console.log('An error occurred: ' + err.message);
            })
            .on('end', function () {
                console.log('Processing finished !');
            });
        let videoStream = ffmpegCommand.pipe();
        videoStream.pipe(res);
    });

    app.listen(6789, () => {
        console.log('localhost:6789')
    });

})();

创建一个独立的server-child.js文件,开启子里程运行video-server.js

(function () {
    'use strict';

    const path = require('path');
    const cp = require('child_process');
    cp.fork(path.join(__dirname,'/renderer/video-server.js'));
})();

使用(非核心代码)

html文件

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <!-- https://electronjs.org/docs/tutorial/security#csp-meta-tag -->
    <!-- 注意下面这一行代码 -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com; style-src 'self' 'unsafe-inline'; media-src *;connect-src *;script-src * 'unsafe-inline' 'unsafe-eval';" />
    <script src="renderer/server-child.js"></script>
</head>
<body>
<h1>Hello World!</h1>
<div><label>请选择视频<input id="file-video" type="file"></label></div>
<div><button id="show-video">显示视频</button></div>
<div><button id="stop-video">停止播放</button></div>
<video src="" width="800" height="450" loop="loop" autoplay="autoplay">
</video>
<script src="renderer/index.js"></script>
</body>
</html>

index.js文件

window.onload = function () {
    let fileVideo = this.document.querySelector('#file-video');
    let showVideo = this.document.querySelector('#show-video');
    let stopVideo = this.document.querySelector('#stop-video');
    let video = this.document.querySelector('video');
    video.addEventListener('canplay', function () {
        video.play();
    });
    showVideo.addEventListener('click', function () {
        let files = fileVideo.files;
        if (!files.length) {
            return;
        }
        let path = files[0].path.replace(/\\/g, '/');
        if (path.endsWith('.mp4')) {
            video.src = path; //mp4文件直接播放
            return;
        }
        video.src = 'http://127.0.0.1:6789/video?video=' + encodeURIComponent(files[0].path.replace(/\\/g, '/')); //非mp4文件通过http推流播放
    });
    stopVideo.addEventListener('click', function () {
        video.src = '';
    });
}
 类似资料: