From 9c7e93ecf8768f9c6b310f89a5e8bc69aba555e3 Mon Sep 17 00:00:00 2001 From: James Taylor Date: Mon, 6 Sep 2021 12:58:27 -0700 Subject: Redo av codec settings & selections to accomodate webm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows for ranked preferences for h264, av1, and vp9 codecs in settings, along with equal preferences which are tiebroken using smaller file size. For each quality, gives av-merge a list of video sources and audio sources sorted based on preference & file size. It will pick the first one that the browser supports. Closes #84 Signed-off-by: Jesús --- youtube/static/js/av-merge.js | 69 +++++++++++++++++++++++++---------------- youtube/static/js/plyr-start.js | 6 ++-- youtube/static/js/watch.js | 12 +++---- 3 files changed, 51 insertions(+), 36 deletions(-) (limited to 'youtube/static/js') diff --git a/youtube/static/js/av-merge.js b/youtube/static/js/av-merge.js index 6ba7f79..bbe3e35 100644 --- a/youtube/static/js/av-merge.js +++ b/youtube/static/js/av-merge.js @@ -19,13 +19,12 @@ // TODO: Call abort to cancel in-progress appends? -function AVMerge(video, srcPair, startTime){ - this.videoSource = srcPair[0]; - this.audioSource = srcPair[1]; - if (this.videoSource.bitrate && this.audioSource.bitrate) - this.avRatio = this.audioSource.bitrate/this.videoSource.bitrate; - else - this.avRatio = 1/10; + + +function AVMerge(video, srcInfo, startTime){ + this.audioSource = null; + this.videoSource = null; + this.avRatio = null; this.videoStream = null; this.audioStream = null; this.seeking = false; @@ -36,30 +35,48 @@ function AVMerge(video, srcPair, startTime){ this.opened = false; this.audioEndOfStreamCalled = false; this.videoEndOfStreamCalled = false; - this.setup(); -} -AVMerge.prototype.setup = function() { if (!('MediaSource' in window)) { reportError('MediaSource not supported.'); return; } - var audioSupported = MediaSource.isTypeSupported( - this.audioSource['mime_codec'] - ) - var videoSupported = MediaSource.isTypeSupported( - this.videoSource['mime_codec'] - ) - if (!audioSupported) - reportError('Unsupported MIME type or codec: ', - this.audioSource['mime_codec']); - if (!videoSupported) - reportError('Unsupported MIME type or codec: ', - this.videoSource['mime_codec']); - if (audioSupported && videoSupported) { - this.mediaSource = new MediaSource(); - this.video.src = URL.createObjectURL(this.mediaSource); - this.mediaSource.onsourceopen = this.sourceOpen.bind(this); + + // Find supported video and audio sources + for (var src of srcInfo['videos']) { + if (MediaSource.isTypeSupported(src['mime_codec'])) { + reportDebug('Using video source', src['mime_codec'], + src['quality_string'], 'itag', src['itag']); + this.videoSource = src; + break; + } } + for (var src of srcInfo['audios']) { + if (MediaSource.isTypeSupported(src['mime_codec'])) { + reportDebug('Using audio source', src['mime_codec'], + src['quality_string'], 'itag', src['itag']); + this.audioSource = src; + break; + } + } + if (this.videoSource === null) + reportError('No supported video MIME type or codec found: ', + srcInfo['videos'].map(s => s.mime_codec).join(', ')); + if (this.audioSource === null) + reportError('No supported audio MIME type or codec found: ', + srcInfo['audios'].map(s => s.mime_codec).join(', ')); + if (this.videoSource === null || this.audioSource === null) + return; + + if (this.videoSource.bitrate && this.audioSource.bitrate) + this.avRatio = this.audioSource.bitrate/this.videoSource.bitrate; + else + this.avRatio = 1/10; + + this.setup(); +} +AVMerge.prototype.setup = function() { + this.mediaSource = new MediaSource(); + this.video.src = URL.createObjectURL(this.mediaSource); + this.mediaSource.onsourceopen = this.sourceOpen.bind(this); } AVMerge.prototype.sourceOpen = function(_) { diff --git a/youtube/static/js/plyr-start.js b/youtube/static/js/plyr-start.js index a72ab9c..82b32d6 100644 --- a/youtube/static/js/plyr-start.js +++ b/youtube/static/js/plyr-start.js @@ -20,10 +20,10 @@ qualityOptions.push(src.quality_string) } for (var src of data['pair_sources']) { - qualityOptions.push(src[0].quality_string) + qualityOptions.push(src.quality_string) } if (data['using_pair_sources']) - qualityDefault = data['pair_sources'][data['pair_idx']][0].quality_string; + qualityDefault = data['pair_sources'][data['pair_idx']].quality_string; else if (data['uni_sources'].length != 0) qualityDefault = data['uni_sources'][data['uni_idx']].quality_string; else @@ -108,7 +108,7 @@ } } else { for (var i=0; i < data['pair_sources'].length; i++) { - if (data['pair_sources'][i][0].quality_string == quality) { + if (data['pair_sources'][i].quality_string == quality) { changeQuality({'type': 'pair', 'index': i}); return; } diff --git a/youtube/static/js/watch.js b/youtube/static/js/watch.js index f7e6285..0954f5b 100644 --- a/youtube/static/js/watch.js +++ b/youtube/static/js/watch.js @@ -4,16 +4,15 @@ function changeQuality(selection) { var currentVideoTime = video.currentTime; var videoPaused = video.paused; var videoSpeed = video.playbackRate; - var videoSource; + var srcInfo; if (avMerge) avMerge.close(); if (selection.type == 'uni'){ - videoSource = data['uni_sources'][selection.index]; - video.src = videoSource.url; + srcInfo = data['uni_sources'][selection.index]; + video.src = srcInfo.url; } else { - let srcPair = data['pair_sources'][selection.index]; - videoSource = srcPair[0]; - avMerge = new AVMerge(video, srcPair, currentVideoTime); + srcInfo = data['pair_sources'][selection.index]; + avMerge = new AVMerge(video, srcInfo, currentVideoTime); } video.currentTime = currentVideoTime; if (!videoPaused){ @@ -26,7 +25,6 @@ function changeQuality(selection) { var avMerge; if (data.using_pair_sources) { var srcPair = data['pair_sources'][data['pair_idx']]; - var videoSource = srcPair[0]; // Do it dynamically rather than as the default in jinja // in case javascript is disabled avMerge = new AVMerge(video, srcPair, 0); -- cgit v1.2.3