Created
February 17, 2016 23:31
-
-
Save samelie/48911ecb689856daa9a0 to your computer and use it in GitHub Desktop.
Youtube SIDX parsed from index range on dash video
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//the index range will be eg: 0-917 | |
// you can find the index range of a particular dash video insode the ytplayer.config | |
// https://github.com/fent/node-ytdl-core | |
function sidxFromInitRange(url, indexRange) { | |
return new Q(function(resolve, reject) { | |
var XMLHttpRequest = require('xhr2'); | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', url); | |
xhr.setRequestHeader("Range", "bytes=" + indexRange); | |
xhr.send(); | |
xhr.responseType = 'arraybuffer'; | |
try { | |
xhr.addEventListener("readystatechange", function() { | |
if (xhr.readyState == xhr.DONE) { // wait for video to load | |
// Add response to buffer | |
var p = require('./sidx').parseSidx(xhr.response); | |
resolve(p); | |
} | |
}, false); | |
} catch (e) { | |
reject(e); | |
} | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//---------------------------- | |
// SIDX | |
//---------------------------- | |
var SIDX = (function SIDX() { | |
function parseSidx(data, byteOffset) { | |
if(!data){ | |
return undefined; | |
} | |
var d = new DataView(data), | |
sidx = new DashSidx(), | |
pos = 0, | |
offset, | |
time, | |
sidxEnd, | |
i, | |
ref_type, | |
ref_size, | |
ref_dur, | |
type, | |
size, | |
mediaRange, | |
startRange, | |
duration, | |
endRange, | |
charCode; | |
while (type !== "sidx" && pos < d.byteLength) { | |
size = d.getUint32(pos); // subtract 8 for including the size and type | |
pos += 4; | |
type = ""; | |
for (i = 0; i < 4; i += 1) { | |
charCode = d.getInt8(pos); | |
type += String.fromCharCode(charCode); | |
pos += 1; | |
} | |
if (type !== "moof" && type !== "traf" && type !== "sidx") { | |
pos += size - 8; | |
} else if (type === "sidx") { | |
// reset the position to the beginning of the box... | |
// if we do not reset the position, the evaluation | |
// of sidxEnd to ab.byteLength will fail. | |
pos -= 8; | |
} | |
} | |
sidxEnd = d.getUint32(pos, false) + pos; | |
if (sidxEnd > data.byteLength) { | |
throw "sidx terminates after array buffer"; | |
return null; | |
} | |
sidx.version = d.getUint8(pos + 8); | |
pos += 12; | |
// skipped reference_ID(32) | |
sidx.timescale = d.getUint32(pos + 4, false); | |
pos += 8; | |
if (sidx.version === 0) { | |
sidx.earliestPresentationTime = d.getUint32(pos, false); | |
sidx.firstOffset = d.getUint32(pos + 4, false); | |
pos += 8; | |
} else { | |
// TODO(strobe): Overflow checks | |
sidx.earliestPresentationTime = MathUtil.to64BitNumber(d.getUint32(pos + 4, false), d.getUint32(pos, false)); | |
//first_offset = utils.Math.to64BitNumber(d.getUint32(pos + 8, false), d.getUint32(pos + 12, false)); | |
sidx.firstOffset = (d.getUint32(pos + 8, false) << 32) + d.getUint32(pos + 12, false); | |
pos += 16; | |
} | |
sidx.firstOffset += sidxEnd + (byteOffset || 0); | |
// skipped reserved(16) | |
sidx.referenceCount = d.getUint16(pos + 2, false); | |
pos += 4; | |
sidx.references = []; | |
offset = sidx.firstOffset; | |
time = sidx.earliestPresentationTime; | |
console.log('\t reference count:', sidx.referenceCount); | |
for (i = 0; i < sidx.referenceCount; i += 1) { | |
ref_size = d.getUint32(pos, false); | |
ref_type = (ref_size >>> 31); | |
ref_size = ref_size & 0x7fffffff; | |
ref_dur = d.getUint32(pos + 4, false); | |
endRange = (offset + ref_size - 1); | |
startRange = offset; | |
mediaRange = startRange + '-' + endRange; | |
pos += 12; | |
sidx.references.push( | |
new DashSidxReference(ref_size, ref_type, offset, ref_dur, time, sidx.timescale, mediaRange, startRange, endRange, ref_dur / sidx.timescale, time / sidx.timescale) | |
); | |
offset += ref_size; | |
time += ref_dur; | |
} | |
if (pos !== sidxEnd) { | |
throw "Error: final pos " + pos + " differs from SIDX end " + sidxEnd; | |
return null; | |
} | |
return sidx; | |
} | |
function DashSidxReference(size, type, offset, duration, time, timescale, mediaRange, startRange, endRange, durationSec, startTimeSec) { | |
this.size = size; | |
this.type = type; | |
this.offset = offset; | |
this.duration = duration; | |
this.time = time; | |
this.timescale = timescale; | |
this.mediaRange = mediaRange; | |
this.startRange = startRange; | |
this.endRange = endRange; | |
this.durationSec = durationSec; | |
this.startTimeSec = startTimeSec; | |
} | |
function DashSidx() { | |
var version = undefined; | |
var timescale = undefined; | |
var earliestPresentationTime = undefined; | |
var firstOffset = undefined; | |
var referenceCount = undefined; | |
var references = DashSidxReference; | |
return { | |
version: version, | |
timescale: timescale, | |
earliestPresentationTime: earliestPresentationTime, | |
firstOffset: firstOffset, | |
referenceCount: referenceCount, | |
references: references | |
} | |
} | |
return { | |
parseSidx: parseSidx | |
} | |
})(); | |
module.exports = SIDX; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment