Recently, I have been watching movies with English subtitles, but my listening level is not good. I want to play back some subtitles for several times. This is a relatively niche requirement, found that current players do not support. So want to achieve their own subtitles playback function of the player. Cross-platform open source players, such as VLC and MPV, have high barriers to development. If you can use Electron as a player, it should be easier to add some personality features, just write some HTML and JS. The biggest problem with Electron is that the H5 Video TAB only supports some video formats. After a period of research, the problem has been solved. At present, the cross-platform all-in-one player based on Electron has been implemented, and has added the playback function of subtitles dialogue that I want most.

All video formats are supported using FFMPEG

In Electron, the H5 Video TAB supports a local path for video. The H5 Video TAB supports only some video formats (MP4, WebM, and OGG). Use FFMPEG to support video files in other formats (MKV, RMVB, FLV…) . Here you can use ffMPEG’s NodeJS wrapper library, FluentFfmPEG. Use FFMPEG first to check whether the video file can be played directly with the H5 video label.

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;
}
Copy the code

For formats not supported by the H5 video label, FFMPEG transcoding is required. The Electron application process is divided into the browser rendering process and the NodeJS main process. Nodejs can start an HTTP server that uses FFMPEG real-time transcoding to return fragmeted MP4 video streams recognized by the H5 video tag.

  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);
Copy the code

The SRC property of the front-end H5 video tag is set to the address of the NodeJS video stream

            <video id="video" width="800" height="480" preload>
                <source src="Http://127.0.0.1:8888? startTime=0" type='video/mp4'>
            </video>
Copy the code

Fragmented MP4 video streaming implementation SEEK

The H5 Video > TAB has a default drag control bar, and supports SEEK for ordinary MP4 video streams, generally implemented over HTTP range. However, HTTP Range does not implement SEEK for fragmented MP4 video streaming. Fragmented MP4 video streaming here is fragmented MP4 video streaming in real time with the size of the entire video file unknown. Here we remove the default control bar for the H5 Video TAB and use a custom drag control bar. Get the total length of the video through FFMPEG. Drag while submitting seek Time in the video stream request address. After the HTTP server obtains seek time, it moves the video playback time through the seek parameter of the FFmpeg command.

Open source

Github.com/relaxrock/r…