How to make a HLS video player from my custom make DASH like video player?

牧云@^-^@ 提交于 2020-01-06 07:13:16

问题


I'm making a web video player which can change the video type from 2d to 3d, video quality from 2160p to 144p, video fps from 60fps to 5fps, audio from english to tamil and subtitles from off to other languages. I cannot make my video player work on IOS because IOS supports HLS only. So I need guidance to how my make a HLS video player which will operate EXACTLY like my DASH like video player. I was able to make my DASH like video player from this demo: http://nickdesaulniers.github.io/netfix/demo/bufferAll.html. So if there is a HLS video player demo which shows something similar to this demo, I think I'll manage to make a HLS video player. If HLS cannot make my features, please state another methods. Thanks

Full sample project here: https://drive.google.com/file/d/156mDgIltBGMkXhx4LZfShxv3A8JrwkNP/view?usp=sharing

My Code (This is a small sample of my original video player):

<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> 

回答1:


In iOS, you can get HLS playback in a much simpler fashion, since it is natively supported by the <video>tag. You can simply do <video src="https://example.com/manifest.m3u8"> and it will work.

Alternatively, you can try and use Media Source Extensions there as well, but writing your own player seems overly complicated. I would probably look at hls.js if I were you.



来源:https://stackoverflow.com/questions/53036652/how-to-make-a-hls-video-player-from-my-custom-make-dash-like-video-player

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!