最近在看英文字幕的電影,聽力水平通常,有些字幕對話想多回放幾遍。這個是一個比較小衆的需求,發現目前的播放器都不支持。因而就想本身實現個有字幕回放功能的播放器。跨平臺的開源播放器,好比VLC、MPV,開發的門檻都挺高的。若是能用Electron作播放器的話,添加一些個性的功能,應該會比較簡單,寫一些html、js就能夠。使用Electron製做播放器碰到的最大問題是,H5 video標籤只支持部分的視頻格式。通過一段時間的研究,這個問題已經解決。目前基於Electron的跨平臺全能播放器已經實現,並加上了我最想要的字幕對話回放功能。html
在Electron應用裏,H5 video標籤支持視頻的本地路徑。 H5 video標籤只支持部分的視頻格式(mp四、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視頻流。node
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視頻流的地址git
<video id="video" width="800" height="480" preload>
<source src="http://127.0.0.1:8888?startTime=0" type='video/mp4'>
</video>
複製代碼
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參數將視頻的播放時間移動。github