Я делаю веб-видеоплеер, который может изменять тип видео с 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>