aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Taylor <user234683@users.noreply.github.com>2021-08-24 21:24:03 -0700
committerJesús <heckyel@hyperbola.info>2021-08-29 20:54:06 -0500
commitd942883c786e308d4f15f4edd0d62963789e0482 (patch)
treee83232c7f742f6f6407e077353710a8f8f4233ed
parenta7da23c6da411442dc4ef6af91447820d0b0e517 (diff)
downloadyt-local-d942883c786e308d4f15f4edd0d62963789e0482.tar.lz
yt-local-d942883c786e308d4f15f4edd0d62963789e0482.tar.xz
yt-local-d942883c786e308d4f15f4edd0d62963789e0482.zip
avmerge: Buffer 50 mb ahead in video
Signed-off-by: Jesús <heckyel@hyperbola.info>
-rw-r--r--youtube/static/js/av-merge.js57
1 files changed, 43 insertions, 14 deletions
diff --git a/youtube/static/js/av-merge.js b/youtube/static/js/av-merge.js
index bbc78b5..393b57d 100644
--- a/youtube/static/js/av-merge.js
+++ b/youtube/static/js/av-merge.js
@@ -17,6 +17,8 @@
// SourceBuffer data limits:
// https://developers.google.com/web/updates/2017/10/quotaexceedederror
+// TODO: AVMerge.close()
+// TODO: close stream at end?
// TODO: Better buffering algorithm
// TODO: Call abort to cancel in-progress appends?
@@ -85,6 +87,11 @@ function Stream(avMerge, source, startTime) {
this.url = source['url'];
this.mimeCodec = source['mime_codec']
this.streamType = source['acodec'] ? 'audio' : 'video';
+ if (this.streamType == 'audio') {
+ this.bufferTarget = 5*10**6; // 5 megabytes
+ } else {
+ this.bufferTarget = 50*10**6; // 50 megabytes
+ }
this.initRange = source['init_range'];
this.indexRange = source['index_range'];
@@ -215,14 +222,32 @@ Stream.prototype.shouldFetchNextSegment = function(nextSegment) {
return currentTick > (entry.tickStart + entry.subSegmentDuration*0.15);
}
Stream.prototype.checkBuffer = async function() {
- this.reportDebug('check Buffer');
if (this.avMerge.seeking) {
return;
}
- var nextSegment = this.getSegmentIdx(this.video.currentTime) + 1;
+ // Find the first unbuffered segment, i
+ var currentSegmentIdx = this.getSegmentIdx(this.video.currentTime);
+ var bufferedBytesAhead = 0;
+ var i;
+ for (i = currentSegmentIdx; i < this.sidx.entries.length; i++) {
+ var entry = this.sidx.entries[i];
+ // check if we had it before, but it was deleted by the browser
+ if (entry.have && !this.segmentInBuffer(i)) {
+ this.reportDebug('segment', i, 'deleted by browser');
+ entry.have = false;
+ entry.requested = false;
+ }
+ if (!entry.have) {
+ break;
+ }
+ bufferedBytesAhead += entry.referencedSize;
+ if (bufferedBytesAhead > this.bufferTarget) {
+ return;
+ }
+ }
- if (this.shouldFetchNextSegment(nextSegment)) {
- this.fetchSegmentIfNeeded(nextSegment);
+ if (i < this.sidx.entries.length && !this.sidx.entries[i].requested) {
+ this.fetchSegment(i);
}
}
Stream.prototype.segmentInBuffer = function(segmentIdx) {
@@ -238,7 +263,20 @@ Stream.prototype.segmentInBuffer = function(segmentIdx) {
}
return false;
}
+Stream.prototype.fetchSegment = function(segmentIdx) {
+ entry = this.sidx.entries[segmentIdx];
+ entry.requested = true;
+ fetchRange(
+ this.url,
+ entry.start,
+ entry.end,
+ this.appendSegment.bind(this, segmentIdx),
+ );
+}
Stream.prototype.fetchSegmentIfNeeded = function(segmentIdx) {
+ if (segmentIdx < 0 || segmentIdx >= this.sidx.entries.length){
+ return;
+ }
entry = this.sidx.entries[segmentIdx];
// check if we had it before, but it was deleted by the browser
if (entry.have && !this.segmentInBuffer(segmentIdx)) {
@@ -249,17 +287,8 @@ Stream.prototype.fetchSegmentIfNeeded = function(segmentIdx) {
if (entry.requested) {
return;
}
- if (segmentIdx < 0 || segmentIdx >= this.sidx.entries.length){
- return;
- }
- entry.requested = true;
- fetchRange(
- this.url,
- entry.start,
- entry.end,
- this.appendSegment.bind(this, segmentIdx),
- );
+ this.fetchSegment(segmentIdx);
}
Stream.prototype.handleSeek = async function() {
var segmentIdx = this.getSegmentIdx(this.video.currentTime);