首页 > 解决方案 > 如何从我的自定义制作 DASH 类视频播放器中制作 HLS 视频播放器?

问题描述

我正在制作一个网络视频播放器,它可以将视频类型从 2d 更改为 3d,视频质量从 2160p 更改为 144p,视频 fps 从 60fps 更改为 5fps,音频从英语更改为泰米尔语,字幕从关闭更改为其他语言。我无法让我的视频播放器正常工作,IOS因为仅IOS支持HLS。所以我需要指导我如何制作一个HLS可以像我喜欢的视频播放器一样运行视频DASH播放器。我可以通过这个演示制作我DASH喜欢的视频播放器:http: //nickdesaulniers.github.io/netfix/demo/bufferAll.html。因此,如果有一个HLS视频播放器演示显示类似于此演示的内容,我想我会设法制作一个HLS视频播放器。如果HLS无法制作我的功能,请说明其他方法。谢谢

此处的完整示例项目:https ://drive.google.com/file/d/156mDgIltBGMkXhx4LZfShxv3A8JrwkNP/view?usp=sharing

我的代码(这是我的原始视频播放器的一个小示例):

<html>
<head>
    <meta charset="utf-8"/>
    <title>ORIGINAL</title>
</head>
<body>
    <video controls style="width: 100%; height: 50%;"></video>
    <br>
    <select width="100px">
    </select>
    <br>
    <div id="current_time_message" style="text-align: center; width: 100%; font-size: 25px;"></div>
    <br>
    Note: You can only make the chages using the 'select' before the Total Segements Loaded of this sample.
    <script>
        var set_timer = undefined;
        var content_class = new Content_Class();

        function Content_Class() {
            var video_player = document.querySelector("video");

            var total_segments = 30,
                total_segements_call = false,
                current_segment = 0;

            var mediaSource = undefined,
                sourceBuffer_video = undefined,
                sourceBuffer_audio = undefined;

            var current_video_type = "2d",
                current_video_quality = "2160p",
                current_video_frame_rate = "60fps",
                current_audio = "english",
                current_subtitle = "off",
                changed_content = "";

            var subtitles_list = [[undefined, "english", "English", "to_be_downloaded"], [undefined, "arabic", "Arabic", "to_be_downloaded"]];
            var content_types_list = [["video-type_options", "2d", "3d"], ["video-quality_options", "2160p", "144p"], ["video-fps_options", "60fps", "5fps"], ["audio_options", "tamil", "english"], ["subtitle_options", "off", "english", "arabic"]];
            var main_function_CALLS = "appending",
                video_append_CALLS = undefined,
                audio_append_CALLS = undefined,
                seek_bar_time_change_CALLS = true,
                re_appendable_check_CALLS = 0,
                remove_for_call_change_part2_CALLS = 0,
                new_content_CALLS = 0,
                time_change_reappend_CALLS = 0;

            function url_maker(type, number) {
                var url = "resources/";
                if (type == "video") {
                    return url += type + "/" + current_video_type + "/" + current_video_frame_rate + "/" + current_video_quality + "/" + current_video_type + "_" + current_video_frame_rate + "_" + current_video_quality + "_" + number + ".mp4";
                } else if (type == "audio") {
                    return url += type + "/" + current_audio + "/" + current_audio + "_" + number + ".mp4";
                } else {
                    return url += type + "/" + current_subtitle + "/" + current_subtitle + ".txt";
                }
            }

            function start() {
                mediaSource = new MediaSource();
                video_player.src = URL.createObjectURL(mediaSource);
                for (var x = 0; x < subtitles_list.length; x++)
                {
                    subtitles_list[x][0] = video_player.addTextTrack("captions", undefined, subtitles_list[x][2]);
                }
                mediaSource.addEventListener('sourceopen', function () {
                    mediaSource.duration = total_segments * 5;
                    sourceBuffer_video = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.64000d"');
                    sourceBuffer_video.mode = 'sequence';
                    sourceBuffer_audio = mediaSource.addSourceBuffer('audio/mp4; codecs="mp4a.40.5"');
                    sourceBuffer_audio.mode = 'sequence';
                    Interactions();
                    main_function();
                });
            }

            function Interactions() {
                var current_time_message = document.getElementById("current_time_message");
                var options = document.querySelector("select");

                video_player.ontimeupdate = function () {
                    if (!total_segements_call) {
                        current_time_message.innerHTML = "Video Downloaded from " + new Date(video_player.currentTime * 1000).toISOString().substr(11, 8) + " to " + new Date(current_segment * 1000).toISOString().substr(11, 8);
                    }
                }

                for (var y=0;y<content_types_list.length;y++) {
                    for (var x=1;x<content_types_list[y].length;x++) {
                        var insert = document.createElement("option");
                        insert.text = content_types_list[y][0].split("_")[0].toUpperCase() + ": " + content_types_list[y][x].toUpperCase();
                        options.add(insert);
                    }
                }

                options.onchange = function() {
                    var text = options.options[options.selectedIndex].value;
                    text = text.split(": ");
                    changed_content = text[0].toLowerCase() + "_" + text[1].toLowerCase();
                    main_function_CALLS = "content changed";
                }
            }

            function main_function() {
                if (main_function_CALLS == "appending") {
                    console.log("----------", current_video_type, current_video_frame_rate, current_video_quality, current_audio, current_subtitle, "----------");
                    window.clearTimeout(set_timer);
                    current_segment++;
                    if (current_segment <= total_segments) {
                        appending_sources(current_segment);
                    } else {
                        var current_time_message = document.getElementById("current_time_message");
                        current_time_message.innerHTML = "Total segements Loaded";
                        total_segements_call = true;
                    }
                } else if (main_function_CALLS == "content changed") {
                    change_content();
                }
            }

            function appending_sources(x) {
                video_append_CALLS = false;
                audio_append_CALLS = false;
                request_xhr (url_maker('video', x), 'arraybuffer', ['video', x, sourceBuffer_video], function (buffer) {
                    sourceBuffer_video.addEventListener('updateend', re_appendable_check);
                    sourceBuffer_video.appendBuffer(buffer);
                    video_append_CALLS = true;
                });
                request_xhr (url_maker('audio', x), 'arraybuffer', ['audio', x, sourceBuffer_audio], function (buffer) {
                    sourceBuffer_audio.addEventListener('updateend', re_appendable_check);
                    sourceBuffer_audio.appendBuffer(buffer);
                    audio_append_CALLS = true;
                });
            }

            function re_appendable_check() {
                if (++re_appendable_check_CALLS == 2) {
                    sourceBuffer_video.removeEventListener('updateend', re_appendable_check);
                    sourceBuffer_audio.removeEventListener('updateend', re_appendable_check);
                    re_appendable_check_CALLS = 0;
                    video_player_old_time = parseInt((video_player.currentTime / 5).toString().split(".")[0]);
                    main_function();
                }
            }

            function crash_reappend(sourceBuffer, response, number, id) {
                window.clearTimeout(set_timer);
                try {
                    sourceBuffer.addEventListener('updateend', re_appendable_check);
                    sourceBuffer.appendBuffer(response);
                    console.log("FINALLY Appended " + id + ": " + number);
                } catch (err) {
                    sourceBuffer.removeEventListener('updateend', re_appendable_check);
                    if (main_function_CALLS == "appending") {
                        console.log("Appending Again Failed of " + id + " at " + number);
                        set_timer = window.setTimeout(function(){crash_reappend(sourceBuffer, response, number, id);}, 5000);
                    } else {
                        remove_for_call_change(number);
                    }
                }
            }

            function remove_for_call_change (number) {
                window.clearTimeout(set_timer);
                re_appendable_check_CALLS = 0;
                function remove_for_call_change_part2() {
                    if (++remove_for_call_change_part2_CALLS == 2) {
                        sourceBuffer_video.removeEventListener('updateend', remove_for_call_change_part2);
                        sourceBuffer_audio.removeEventListener('updateend', remove_for_call_change_part2);
                        remove_for_call_change_part2_CALLS = 0;
                        current_segment -= 1;
                        sourceBuffer_video.timestampOffset = current_segment*5;
                        sourceBuffer_audio.timestampOffset = current_segment*5;
                        video_player_old_time = parseInt((video_player.currentTime / 5).toString().split(".")[0]);
                        main_function();
                    }
                }
                if (!sourceBuffer_audio.updating && !sourceBuffer_video.updating) {
                    re_appendable_check_CALLS = 0;
                    sourceBuffer_video.removeEventListener('updateend', re_appendable_check);
                    sourceBuffer_audio.removeEventListener('updateend', re_appendable_check);
                    sourceBuffer_video.addEventListener('updateend', remove_for_call_change_part2);
                    sourceBuffer_audio.addEventListener('updateend', remove_for_call_change_part2);
                    sourceBuffer_video.remove((number*5)-5, number*5);
                    sourceBuffer_audio.remove((number*5)-5, number*5);
                } else {
                    set_timer = window.setTimeout(function(){remove_for_call_change(number);}, 2000);
                }
            }

            function request_xhr(url, responsetype, type, input_function)
            {
                var xhr = new XMLHttpRequest;
                xhr.open('get', url);
                xhr.responseType = responsetype;
                xhr.onload = function() {
                    try {
                        input_function(xhr.response);
                        console.log("Appended " + type[0] + ": " + type[1]);
                    } catch (err) {
                        if (responsetype != "") {
                            console.log("Appending Failed of " + type[0] + " at " + type[1]);
                            type[2].removeEventListener('updateend', re_appendable_check);
                            crash_reappend(type[2], xhr.response, type[1], type[0]);
                        } else {
                            console.log("SUBTITLE FAILED");
                        }
                    }    
                };
                xhr.send();
            }

            function change_content() {
                var change_content_type = changed_content.split("_")[0];
                var change_content = changed_content.split("_")[1].toLowerCase();

                if (change_content_type == "video-type") {
                    if (current_video_type != change_content) {
                        current_video_type = change_content;
                        new_content();
                    } else {main_function_CALLS = "appending";main_function();}
                } else if (change_content_type == "video-quality") {
                    if (current_video_quality != change_content) {
                        current_video_quality = change_content;
                        new_content();
                    } else {main_function_CALLS = "appending";main_function();}
                } else if (change_content_type == "video-fps") {
                    if (current_video_frame_rate != change_content) {
                        current_video_frame_rate = change_content;
                        new_content();
                    } else {main_function_CALLS = "appending";main_function();}
                } else if (change_content_type == "audio") {
                    if (current_audio != change_content) {
                        current_audio = change_content;
                        new_content();
                    } else {main_function_CALLS = "appending";main_function();}
                } else if (change_content_type == "subtitle") {
                    console.log(change_content_type, change_content);
                    if (current_subtitle != change_content) {
                        current_subtitle = change_content;
                        subtitle_change();
                    } else {main_function_CALLS = "appending";main_function();}
                }
                function new_content() {
                    function content_changed_reappend() {
                        if (++new_content_CALLS == 2) {
                        sourceBuffer_video.removeEventListener('updateend', content_changed_reappend);
                        sourceBuffer_audio.removeEventListener('updateend', content_changed_reappend);

                        new_content_CALLS = 0;

                        current_segment = parseInt((video_player.currentTime / 5).toString().split(".")[0]);
                        sourceBuffer_video.timestampOffset = current_segment*5;
                        sourceBuffer_audio.timestampOffset = current_segment*5;
                        main_function_CALLS = "appending";
                        main_function();
                        }
                    }
                    sourceBuffer_video.addEventListener('updateend', content_changed_reappend);
                    sourceBuffer_audio.addEventListener('updateend', content_changed_reappend);

                    sourceBuffer_video.remove(0, total_segments * 5);
                    sourceBuffer_audio.remove(0, total_segments * 5);
                }
                function subtitle_change() {
                    if (current_subtitle == "off") {
                        for (var x = 0; x < subtitles_list.length; x++) {
                            subtitles_list[x][0].mode = "hidden";
                        }
                    } else {
                        for (var x = 0; x < subtitles_list.length; x++) {
                            if (subtitles_list[x][1] == current_subtitle) {
                                if (subtitles_list[x][3] != "downloaded") {
                                    var num = x; //wierd problem
                                    subtitles_list[num][0].mode = "showing";
                                    request_xhr(url_maker("subtitle", 0), "", ['subtitle', 0], function(buffer) {
                                        var file = buffer.split('\n');
                                        for (var y = 0; y < file.length; y+=2) {
                                            subtitles_list[num][0].addCue(new VTTCue(file[y].split(" --> ")[0], file[y].split(" --> ")[1], file[y+1].replace(/\\n/g, '\n')));
                                        }
                                    });
                                    subtitles_list[num][3] = "downloaded";
                                } else {
                                    subtitles_list[x][0].mode = "showing";
                                }
                            } else {
                                subtitles_list[x][0].mode = "hidden";
                            }
                        }
                    }
                    main_function_CALLS = "appending";
                    main_function();
                }
            }
            return {
                start: start
            };
        }
        set_timer = window.setTimeout(content_class.start(), 1);
    </script>
</body>
</html> 

标签: iosvideo-streaminghttp-live-streamingmpeg-dash

解决方案


<video>在 iOS 中,您可以以更简单的方式获得 HLS 播放,因为它是由标签原生支持的。你可以简单地做<video src="https://example.com/manifest.m3u8">,它会工作。

或者,您也可以尝试在那里使用媒体源扩展,但是编写自己的播放器似乎过于复杂。如果我是你,我可能会查看 hls.js。


推荐阅读