首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >支持HTML5 5‘S视频元件的SRT字幕支持

支持HTML5 5‘S视频元件的SRT字幕支持
EN

Code Review用户
提问于 2019-02-21 15:38:09
回答 2查看 822关注 0票数 3

使用HTML5,您可以使用元素向视频添加标题。然而,只有vtt文件是官方支持的,而当前最流行的字幕格式是众所周知的srt格式。

因此,我没有将所有srt文件转换为vtt文件,而是编写了一个脚本,它将实时完成所有这些工作。没有任何手动转换。

使用脚本,可以将srt文件添加到元素中,如下所示:

代码语言:javascript
复制

脚本所做的基本工作如下

  • 使用XMLHttpRequest获取文件中的内容。
  • 将srt格式转换为vtt格式
  • 从vtt字符串创建blob。
  • 从blob创建一个文件。
  • 用生成的vtt文件替换原始的src

脚本本身非常简单和小,只有4kb的大小。我想知道我是否可以使脚本更小,如果我把代码写得很好。

代码语言:javascript
复制
document.addEventListener("DOMContentLoaded", function () {
    /**
     * Get all videos
     */
    var videoElements = document.getElementsByTagName('video');

    /**
     * This function converts all srt's to vtt files
     */
    function convertSrtToVtt() 
    {
        /**
         * Generate an unique identifier
         */
        this.id = '_' + Math.random().toString(36).substr(2, 9);

        /**
         * All tracks assigned to current video element
         */
        var tracks = document.querySelectorAll("#" + this.id + " track");

        var subtitle = {
            data: 
            {
                track: {}
            },
            /**
             * Load the file from url
             *
             * @param {object}    track   - DOM  object
             */
            load: function(track) 
            {
                subtitle.track = track;

                if(subtitle.isSrt(subtitle.track.src)) 
                {
                    var client = new XMLHttpRequest();
                    client.open('GET', subtitle.track.src);
                    client.onreadystatechange = function() 
                    {
                        subtitle.convert(client.responseText).then(
                            function (file) 
                            {
                                /**
                                 * Replace the srt file with the generated vtt file
                                 */
                                subtitle.track.src = file   
                            }
                        );
                    }
                    client.send();
                }
            },
            /**
             * Converts the SRT string to a VTT formatted string
             *
             * @param   {string}    content     - SRT string
             * @return  {object}    promise     - Returns a promise with the generated file as the return value
             */
            convert: function(content) 
            {
                var promise = new Promise( 
                    function (resolve, reject) 
                    {
                        /**
                         * Replace all (,) commas with (.) dots. Eg: 00:00:01,144 -> 00:00:01.144
                         */
                        content = content.replace(/(\d+:\d+:\d+)+,(\d+)/g, '$1.$2');
                        content = "WEBVTT - Generated using SRT2VTT\r\n\r\n" + content;

                        /**
                         * Convert content to a file
                         */
                        var blob = new Blob([content], {type: 'text/vtt'});
                        var file = window.URL.createObjectURL(blob);

                        resolve(file);
                    }
                );

                return promise;
            },
            isSrt: function(filename) 
            {
                return filename.split('.').pop().toLowerCase() === 'srt' ? true : false;
            },
            isVTT: function(filename) 
            {
                return filename.split('.').pop().toLowerCase() === 'vtt' ? true : false;
            }
        }

        for(var i = 0;i < tracks.length;i++) 
        {
            subtitle.load(tracks[i]);
        }
    }

    for(var i = 0;i < videoElements.length;i++) 
    {
        videoElements[i].addEventListener('loadstart', convertSrtToVtt);
    }
});

在CodePen上的工作演示 Github储存库

EN

回答 2

Code Review用户

回答已采纳

发布于 2019-02-21 21:46:37

臃肿

您有104行代码,这些代码可以很容易地通过一些简单的功能来提高可读性。删除注释,同一行打开阻止{,并删除空行。这将代码减少到54行。

评论

我看你对JS有点陌生

一些JS项目

  • 对不更改的变量使用const
  • 在JS中,我们将打开的块分隔符{放在同一行中。
  • 当使用vars时,您应该将它们提升到作用域的顶部。
  • 对匿名函数使用箭头函数。
  • window是默认对象,您不需要使用它。你不是用它来做Blob (如new window.Blob( ),但是下一行你用它做URL,为什么?
  • 使用最短的形式。例如for(var i = 0;i < tracks.length;i++) {索引是不需要的,所以for(const track of tracks)tracks.forEach(subtitle.load)会更好;
  • 不要使用substr,它在折旧的大清单上。使用substringslice
  • 在声明对象函数时使用函数简写。load: function(track) {应该是load(track) {

代码样式与逻辑

  • 注释太高了,只是重复代码中不言自明的内容。
  • if(之间的空间
  • 您没有使用承诺回调的第二个参数,那么为什么要定义它呢?
  • 不要对变量和参数使用泛型名称。new Promise( function (resolve, reject) {没有语义意义,类似于new Promise(converted => {的东西会更贴切。
  • 不要添加冗余代码return filename.split('.').pop().toLowerCase() === 'srt' ? true : false;return filename.split('.').pop().toLowerCase() === 'srt';相同
  • 为什么将两个函数isSrtisVTT添加到对象中。它们是通用的,可以在对象之外定义一次(BTW应该是isSrt还是isSRT,我不知道它代表什么,但是如果是首字母缩略词,那么它应该是大写?)
  • 随机id可以产生小于7个字符的字符串。例如(1/36).toString(36).substr(2, 9)会创建"1"而不是"1000000"
  • 当您已经有要查询的元素时,我看不出创建随机id (冲突的可能性很大)的意义。

结构

  • 为什么在不需要对象subtitle的情况下创建它?
  • 为什么要创建subtitle: { data: { track: {}}...。我找不到任何参考资料。
  • 您可以使用FetchAPI接口而不是XMLHttpRequest

替代示例.

可以消除大量的膨胀,从而可以在一个页面中查看该过程,从而提高了可维护性、可读性,并减少了出现bug的可能性。

代码语言:javascript
复制
document.addEventListener("DOMContentLoaded", function () {
    const isSrt = name => name.split(".").pop().toLowerCase() === "srt";  
    const convert = content => new Promise(converted => {
        content = content.replace(/(\d+:\d+:\d+)+,(\d+)/g, "$1.$2");
        content = "WEBVTT - Generated using SRT2VTT\r\n\r\n" + content;
        converted(URL.createObjectURL(new Blob([content], {type: "text/vtt"})));
    });    
    for (const vid of document.getElementsByTagName("video"))  {
        vid.addEventListener("loadstart", event => {
            const tracks = [...event.target.querySelectorAll("track")];
            tracks.forEach(track => {
                if (isSrt(track.src))  {
                    const client = new XMLHttpRequest();
                    client.open("GET", track.src);
                    client.onreadystatechange = () => {
                        convert(client.responseText).then(file => track.src = file);
                    };
                    client.send();
                }
            });
        }
    }
});

更新

要支持遗留浏览器,您应该使用类似于巴贝尔的内容。请注意,这将不包括媒体textTrack支持,只有javascript

票数 3
EN

Code Review用户

发布于 2019-02-21 22:49:26

破坏每个id元素的属性是意外的,也是不公平的。这可能会破坏页面(例如任何依赖于原始id的CSS规则)。

巨大的convertSrtToVtt()定义位于var videoElements定义和使用这些videoElements的循环之间。对于可读性来说,这是一个巨大的不必要的烦恼。

就我个人而言,我发现

代码语言:javascript
复制
/**
 * Multi-line comments
 */

妨碍可读性,尤指当注释适用于单个语句时。

isVTT函数从未使用过,应该删除。(请注意,它的大写与isSrtconvertSrtToVtt不一致。)

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/213970

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档