博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Electron实现跨平台全能视频播放器
阅读量:5953 次
发布时间:2019-06-19

本文共 3307 字,大约阅读时间需要 11 分钟。

最近在看英文字幕的电影,听力水平一般,有些字幕对话想多回放几遍。这个是一个比较小众的需求,发现目前的播放器都不支持。于是就想自己实现个有字幕回放功能的播放器。跨平台的开源播放器,比如VLC、MPV,开发的门槛都挺高的。如果能用Electron做播放器的话,添加一些个性的功能,应该会比较简单,写一些html、js就可以。使用Electron制作播放器碰到的最大问题是,H5 video标签只支持部分的视频格式。经过一段时间的研究,这个问题已经解决。目前基于Electron的跨平台全能播放器已经实现,并加上了我最想要的字幕对话回放功能。

使用ffmpeg支持所有视频格式

在Electron应用里,H5 video标签支持视频的本地路径。 H5 video标签只支持部分的视频格式(mp4、webm和ogg)。需要使用ffmpeg支持其他格式的视频文件(mkv、rmvb、flv...)。这里可以使用ffmpeg的nodejs封装库 fluentffmpeg。 先使用ffmpeg检查视频文件是否可以直接用H5 video标签直接播放。

var videoSupport = function (videoPath) {    let p = new Promise(function (resolve, reject) {        let command = ffmpeg()            .input(videoPath)            .ffprobe(function (err, data) {                if (err) {                    reject(err);                    return;                }                var streams = data.streams;                var checkResult = {                    videoCodecSupport: false,                    audioCodecSupport: false,                    duration: data.format.duration                }                if (streams) {                    streams.map((value) => {                        // mp4, webm, ogg                        if (value.codec_type == 'video' && (value.codec_name == 'h264' ||                         value.codec_name == 'vp8' || value.codec_name == 'theora')) {                            checkResult.videoCodecSupport = true;                        }                        if (value.codec_type == 'audio' && (value.codec_name == 'aac' ||                         value.codec_name == 'vorbis')) {                            checkResult.audioCodecSupport = true;                        }                    })                }                resolve(checkResult)            });    });    return p;}复制代码

对于H5 video标签不支持的格式,需要ffmpeg转码。 Electron应用进程分为浏览器渲染进程,和nodejs主进程。nodejs可以启动http server,这个http server使用ffmpeg实时转码,返回H5 video标签可以识别的fragmeted mp4视频流。

this._videoServer = http.createServer((request, response) => {                var startTime = parseInt(getParam(request.url, "startTime"));                let videoCodec = this.videoSourceInfo.checkResult.videoCodecSupport ? 'copy' : 'libx264';                let audioCodec = this.videoSourceInfo.checkResult.audioCodecSupport ? 'copy' : 'aac';                this.killFfmpegCommand();                this._ffmpegCommand = ffmpeg()                    .input(this.videoSourceInfo.videoSourcePath)                    // read input at native framerate                    .nativeFramerate()                    .videoCodec(videoCodec)                    .audioCodec(audioCodec)                    .format('mp4')                    .seekInput(startTime)                    // fragmeted mp4                    .outputOptions('-movflags', 'frag_keyframe+empty_moov');                let videoStream = this._ffmpegCommand.pipe();                videoStream.pipe(response);            }).listen(8888);复制代码

前端H5 video标签src属性设置为nodejs视频流的地址

复制代码

Fragmented mp4视频流seek的实现

H5 video>标签有默认的拖动控制条,支持普通mp4视频流的seek,一般通过http range实现。但是对fragmented mp4视频流,http range无法实现seek。这里的fragmented mp4视频流是实时的转码流,整个视频文件的size是未知的。 这里我们去掉了H5 video标签的默认控制条,使用自定义的拖动控制条。通过ffmpeg获得视频的总时长。拖动的时候在视频流的请求地址里面提交seek time。http server获得seek time后,通过ffmpeg命令的seek参数将视频的播放时间移动。

开源

转载于:https://juejin.im/post/5c034f40f265da616a476758

你可能感兴趣的文章
面向服务的架构SOA
查看>>
lnmp+lamp编译后,编译参数查看
查看>>
OEL7.2下Oracle11.2.0.4RAC部署
查看>>
nagios安装与配置
查看>>
RedHat 设置IP、网关、DNS
查看>>
MYSQL 主从复制读写分离实现
查看>>
linux更改语言
查看>>
centos7 修改mac地址
查看>>
获取Java项目根目录
查看>>
我的友情链接
查看>>
堆排序
查看>>
<script>标签的加载解析执行
查看>>
恢复rm删除的文件(ext3
查看>>
我的友情链接
查看>>
账户注销完自动登录账户,并且不需要再点击屏幕的账户头像
查看>>
【Interface&navigation】按钮(29)
查看>>
我要学python之装饰器
查看>>
Extjs4.x (MVC)Controller中refs以及Ext.ComponentQuery解析
查看>>
消息最终一致性解决方案之RabbitMQ实现
查看>>
记录:网络通信协议中的TCP/IP与UDP
查看>>