Skip to content

Commit

Permalink
fix: calculating segment start time in live dash-mpd
Browse files Browse the repository at this point in the history
fixes #21 again
  • Loading branch information
fent committed Dec 9, 2018
1 parent 956e229 commit 9dbd89a
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 22 deletions.
25 changes: 15 additions & 10 deletions lib/dash-mpd-parser.js
@@ -1,5 +1,6 @@
const Writable = require('stream').Writable;
const sax = require('sax');
const Writable = require('stream').Writable;
const sax = require('sax');
const parseTime = require('./parse-time');


/**
Expand All @@ -20,9 +21,10 @@ module.exports = class DashMPDParser extends Writable {
let segmentTemplate;
let timescale, offset, duration, baseURL;
let timeline = [];
let getSegments = false, startEmitted = false;
let getSegments = false;
let isStatic;
let treeLevel;
let periodStart;

const tmpl = (str) => {
const context = {
Expand All @@ -48,19 +50,13 @@ module.exports = class DashMPDParser extends Writable {
offset = 0;
baseURL = [];
treeLevel = 0;
periodStart = parseTime.durationStr(node.attributes.start) || 0;
break;
case 'segmentlist':
seq = parseInt(node.attributes.startnumber) || seq;
timescale = parseInt(node.attributes.timescale) || timescale;
duration = parseInt(node.attributes.duration) || duration;
offset = parseInt(node.attributes.presentationtimeoffset) || offset;
if (!startEmitted) {
startEmitted = true;
if (offset) {
currtime += offset;
}
this.emit('starttime', currtime);
}
break;
case 'segmenttemplate':
segmentTemplate = node.attributes;
Expand All @@ -84,6 +80,15 @@ module.exports = class DashMPDParser extends Writable {
targetID = node.attributes.id;
}
getSegments = node.attributes.id === targetID + '';
if (getSegments) {
if (periodStart) {
currtime += periodStart;
}
if (offset) {
currtime -= offset / timescale * 1000;
}
this.emit('starttime', currtime);
}
if (getSegments && segmentTemplate && timeline.length) {
if (segmentTemplate.initialization) {
this.emit('item', {
Expand Down
2 changes: 1 addition & 1 deletion lib/index.js
Expand Up @@ -27,7 +27,7 @@ module.exports = (playlistURL, options) => {
}
let relativeBegin = typeof options.begin === 'string';
let begin = relativeBegin ?
parseTime(options.begin) :
parseTime.humanStr(options.begin) :
Math.max(options.begin - liveBuffer, 0) || 0;
let liveBegin = Date.now() - liveBuffer;

Expand Down
18 changes: 17 additions & 1 deletion lib/parse-time.js
Expand Up @@ -14,7 +14,7 @@ const timeUnits = {
m: 60000,
h: 3600000,
};
module.exports = (time) => {
exports.humanStr = (time) => {
if (typeof time === 'number') { return time; }
if (numberFormat.test(time)) { return +time; }
const firstFormat = timeFormat.exec(time);
Expand All @@ -33,3 +33,19 @@ module.exports = (time) => {
return total;
}
};

/**
* Parses a duration string in the form of "123.456S", returns milliseconds.
*
* @param {string} time
* @return {number}
*/
exports.durationStr = (time) => {
let total = 0;
const r = /(\d+(?:\.\d+)?)(S|M|H)/g;
let rs;
while ((rs = r.exec(time)) != null) {
total += +rs[1] * timeUnits[rs[2].toLowerCase()];
}
return total;
};
3 changes: 3 additions & 0 deletions test/dash-mpd-parser-test.js
Expand Up @@ -11,12 +11,15 @@ describe('dash MPD parser', () => {
let items = [];
let endlist = false;
const parser = new DashMPDParser();
let starttime;
parser.on('starttime', a => starttime = a);
parser.on('item', (item) => { items.push(item); });
parser.on('endlist', () => { endlist = true; });
parser.on('error', done);
let rs = fs.createReadStream(filepath);
rs.pipe(parser);
rs.on('end', () => {
assert.equal(new Date(starttime).toISOString(), '2018-08-20T16:24:21.942Z');
assert.ok(!endlist);
assert.deepEqual(items, [
{ url: 'https://videohost.com/139/0001.ts',
Expand Down
20 changes: 10 additions & 10 deletions test/parse-time-test.js
Expand Up @@ -4,21 +4,21 @@ const parseTime = require('../lib/parse-time');

describe('parse-time', () => {
it('Time format 00:00:00.000', () => {
assert.equal(parseTime('25.000'), 25000);
assert.equal(parseTime('05:30'), 60000 * 5 + 30000);
assert.equal(parseTime('01:05:30'), 60000 * 60 + 60000 * 5 + 30000);
assert.equal(parseTime('1:30.123'), 60000 + 30000 + 123);
assert.equal(parseTime.humanStr('25.000'), 25000);
assert.equal(parseTime.humanStr('05:30'), 60000 * 5 + 30000);
assert.equal(parseTime.humanStr('01:05:30'), 60000 * 60 + 60000 * 5 + 30000);
assert.equal(parseTime.humanStr('1:30.123'), 60000 + 30000 + 123);
});

it('Time format 0ms, 0s, 0m, 0h', () => {
assert.equal(parseTime('2ms'), 2);
assert.equal(parseTime('1m'), 60000);
assert.equal(parseTime('1m10s'), 60000 + 10000);
assert.equal(parseTime('2hm10s500ms'), 3600000 * 2 + 10000 + 500);
assert.equal(parseTime.humanStr('2ms'), 2);
assert.equal(parseTime.humanStr('1m'), 60000);
assert.equal(parseTime.humanStr('1m10s'), 60000 + 10000);
assert.equal(parseTime.humanStr('2hm10s500ms'), 3600000 * 2 + 10000 + 500);
});

it('No format', () => {
assert.equal(parseTime('1000'), 1000);
assert.equal(parseTime(200), 200);
assert.equal(parseTime.humanStr('1000'), 1000);
assert.equal(parseTime.humanStr(200), 200);
});
});

0 comments on commit 9dbd89a

Please sign in to comment.