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

说明

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

npm依赖

javascript 复制代码
"dependencies": {
    "@ffmpeg-installer/ffmpeg": "1.0.20",
    "fluent-ffmpeg": "2.1.2",
    "express": "^4.17.1"
  }

核心代码

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

javascript 复制代码
(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

javascript 复制代码
(function () {
    'use strict';

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

使用(非核心代码)

html文件

handlebars 复制代码
<!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文件

javascript 复制代码
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 = '';
    });
}
相关推荐
IT_陈寒18 分钟前
Redis缓存击穿把我坑惨了,原来这样设过期时间才靠谱
前端·人工智能·后端
用户9385156350732 分钟前
从"坐电梯"到"前端路由"——深入理解 Hash 路由原理
前端·typescript·全栈
梦想CAD控件1 小时前
网页端CAD的图形选择、编辑与夹点操作教程
前端·javascript·node.js
妙码生花1 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(五十二):管理员权限检查中间件,AI 随意放行预闯大祸
前端·后端·go
月月大王的3D日记1 小时前
Three.js 入门系列(8):六种光源全解析 —— 关灯了,开光!
前端·javascript
属于自己的天空2 小时前
每天省去重复 Prompt:我用 Skills 把 CRUD 生成标准化了
前端·后端
卡卡罗特AI2 小时前
GitHub怎么用?零基础,保姆级使用教程-上!建议收藏
前端·后端·github
自然 醒2 小时前
v-tooltip自定义指令封装
前端·javascript·vue.js
因_崔斯汀2 小时前
Three.js 3D 热力云图效果实现
前端·three.js