Ver código fonte

Update m3u8parse & hls-segment-reader dependencies

Gil Pedersen 9 anos atrás
pai
commit
7e4d332dc4
6 arquivos alterados com 59 adições e 43 exclusões
  1. 2 1
      .eslintrc
  2. 2 2
      bin/hlsmon
  3. 1 1
      lib/hls-reader.js
  4. 23 29
      lib/recorder.js
  5. 28 7
      lib/segment-decrypt.js
  6. 3 3
      package.json

+ 2 - 1
.eslintrc

@@ -1,6 +1,7 @@
 {
     "env": {
-        "node": true
+        "node": true,
+        "es6": true
     },
     "rules": {
         "quotes": 0,

+ 2 - 2
bin/hlsmon

@@ -35,8 +35,8 @@ function monitor(srcUrl) {
   });
 
   r.on('end', function() {
-    if (r.index && r.index.variant) {
-      var newUrl = url.resolve(r.baseUrl, r.index.programs['1'][0].uri);
+    if (r.index && r.index.master) {
+      var newUrl = url.resolve(r.baseUrl, r.index.variants[0].uri);
       console.error('found variant index, using: ', newUrl);
       return monitor(newUrl);
     }

+ 1 - 1
lib/hls-reader.js

@@ -65,7 +65,7 @@ function HlsReader(segmentReader, options) {
   StreamEach(this.reader, function (segmentInfo, done) {
     self.isReading = true;
 
-    return self.decrypt(segmentInfo.stream, segmentInfo.details.key, function (err, stream) {
+    return self.decrypt(segmentInfo.stream, segmentInfo.details.keys, function (err, stream) {
       if (err) {
         console.error('decrypt failed', err.stack);
         stream = segmentInfo.stream;

+ 23 - 29
lib/recorder.js

@@ -10,7 +10,7 @@ var fs = require('fs'),
 var mime = require('mime-types'),
     StreamEach = require('stream-each'),
     oncemore = require('oncemore'),
-    m3u8parse = require('m3u8parse'),
+    M3U8Parse = require('m3u8parse'),
     mkdirp = require('mkdirp'),
     writeFileAtomic = require('write-file-atomic'),
     debug = require('debug')('hls:recorder');
@@ -57,8 +57,8 @@ HlsStreamRecorder.prototype.updateIndex = function(update) {
   if (!update) return;
 
   if (!this.index) {
-    this.index = new m3u8parse.M3U8Playlist(update);
-    if (!this.index.variant) {
+    this.index = new M3U8Parse.M3U8Playlist(update);
+    if (!this.index.master) {
       if (this.collect)
         this.index.version = Math.max(4, this.index.version);  // v4 is required for byterange support
       this.index.version = Math.max(2, this.index.version);    // v2 is required to support the remapped IV attribute
@@ -77,45 +77,39 @@ HlsStreamRecorder.prototype.updateIndex = function(update) {
         this.index.start.decimalInteger('time-offset', offset);
       }
     } else {
-      debug('programs', this.index.programs);
+      debug('variants', this.index.variants);
       if (this.subreader) {
-        var programNo = Object.keys(this.index.programs)[0];
-        var programs = this.index.programs[programNo];
-
         // remove backup sources
-        var used = {};
-        programs = programs.filter(function(program) {
-          var bw = parseInt(program.info.bandwidth, 10);
-          var res = !(bw in used);
+        let used = {};
+        this.index.variants = this.index.variants.filter((variant) => {
+          let bw = parseInt(variant.info.bandwidth, 10);
+          let res = !(bw in used);
           used[bw] = true;
           return res;
         });
 
-        this.index.programs[programNo] = programs;
-
-        programs.forEach(function(program, index) {
-          var programUrl = url.resolve(self.reader.baseUrl, program.uri);
-          debug('url', programUrl);
+        this.index.variants.forEach((variant, index) => {
+          var variantUrl = url.resolve(self.reader.baseUrl, variant.uri);
+          debug('url', variantUrl);
 
           // check for duplicate source urls
-          var rec = this.recorderForUrl(programUrl);
+          var rec = this.recorderForUrl(variantUrl);
           if (!rec || !rec.localUrl) {
-            var dir = self.variantName(program.info, index);
-            rec = new HlsStreamRecorder(self.subreader(programUrl), path.join(self.dst, dir), { startOffset: self.startOffset, collect: self.collect, decrypt: this.decrypt });
+            var dir = self.variantName(variant.info, index);
+            rec = new HlsStreamRecorder(self.subreader(variantUrl), path.join(self.dst, dir), { startOffset: self.startOffset, collect: self.collect, decrypt: this.decrypt });
             rec.localUrl = url.format({pathname: path.join(dir, 'index.m3u8')});
-            rec.remoteUrl = programUrl;
+            rec.remoteUrl = variantUrl;
 
             this.recorders.push(rec);
           }
 
-          program.uri = rec.localUrl;
-        }, this);
+          variant.uri = rec.localUrl;
+        });
 
         var allGroups = [];
         for (var group in this.index.groups)
           [].push.apply(allGroups, this.index.groups[group]);
 
-
         allGroups.forEach(function(groupItem, index) {
           var srcUri = groupItem.quotedString('uri');
           if (srcUri) {
@@ -141,11 +135,11 @@ HlsStreamRecorder.prototype.updateIndex = function(update) {
           recording.start();
         });
 
-        this.index.iframes = {};
+        this.index.iframes = [];
       } else {
-        this.index.programs = {};
+        this.index.variants = [];
         this.index.groups = {};
-        this.index.iframes = {};
+        this.index.iframes = [];
       }
     }
 
@@ -170,7 +164,7 @@ HlsStreamRecorder.prototype.updateIndex = function(update) {
 HlsStreamRecorder.prototype.process = function(segmentInfo, done) {
   var self = this;
 
-  var segment = new m3u8parse.M3U8Segment(segmentInfo.details, true);
+  var segment = new M3U8Parse.M3U8Segment(segmentInfo.details, true);
   var meta = segmentInfo.file;
 
   // mark discontinuities
@@ -195,12 +189,12 @@ HlsStreamRecorder.prototype.process = function(segmentInfo, done) {
   }
 
   // save the stream segment
-  SegmentDecrypt.decrypt(segmentInfo.stream, segmentInfo.details.key, this.decrypt, function (err, stream, decrypted) {
+  SegmentDecrypt.decrypt(segmentInfo.stream, segmentInfo.details.keys, this.decrypt, function (err, stream, decrypted) {
     if (err) {
       console.error('decrypt failed', err.stack);
       stream = segmentInfo.stream;
     } else if (decrypted) {
-      segment.key = null;
+      segment.keys = null;
     }
 
     stream = oncemore(stream);

+ 28 - 7
lib/segment-decrypt.js

@@ -79,32 +79,53 @@ internals.fetchKey = function (keyUri, options, next) {
 };
 
 
+internals.getIdentityKey = function (keyAttrs) {
+  for (let idx = 0; idx < keyAttrs.length; idx++) {
+    let key = keyAttrs[idx];
+    let keyformat = key.quotedString('keyformat');
+    if (!keyformat || keyformat === 'identity') {
+      return {
+        method: key.enumeratedString('method'),
+        uri: key.quotedString('uri'),
+        iv: key.hexadecimalInteger('iv')
+      };
+    }
+  }
+
+  return null;
+};
+
+
 exports.decrypt = function (stream, keyAttrs, options, next) {
-  var method = keyAttrs && keyAttrs.enumeratedString('method');
-  if (!options || !method || method === 'NONE') {
+  if (!keyAttrs || !options) {
+    return next(null, stream, false);
+  }
+
+  let key = internals.getIdentityKey(keyAttrs);
+  if (!key || key.method === 'NONE') {
     return next(null, stream, false);
   }
 
-  if (method !== 'AES-128' || !keyAttrs.quotedString('uri') || !keyAttrs.hexadecimalInteger('iv')) {
+  if (key.method !== 'AES-128' || !key.uri || !key.iv) {
 
     // TODO: hard error when key is not recognized?
     return next(new Error('unknown encryption parameters'), stream);
   }
 
-  return internals.fetchKey(keyAttrs.quotedString('uri'), options, function(err, key) {
+  return internals.fetchKey(key.uri, options, (err, keyData) => {
     if (err) {
       return next(new Error('key fetch failed: ' + (err.stack || err)));
     }
 
-    var iv = keyAttrs.hexadecimalInteger('iv');
+    let decrypt;
     try {
-      var decrypt = Crypto.createDecipheriv('aes-128-cbc', key, iv);
+      decrypt = Crypto.createDecipheriv('aes-128-cbc', keyData, key.iv);
     } catch (ex) {
       return next(new Error('crypto setup failed: ' + (ex.stack || ex)));
     }
 
     // forward stream errors
-    stream.on('error', function(err) {
+    stream.on('error', (err) => {
       decrypt.emit('error', err);
     });
 

+ 3 - 3
package.json

@@ -29,8 +29,8 @@
     "commander": "^2.3.0",
     "debug": "^2.0.0",
     "deep-equal": "^1.0.0",
-    "hls-segment-reader": "^2.0.0",
-    "m3u8parse": "^0.2.2",
+    "hls-segment-reader": "^3.0.0",
+    "m3u8parse": "^1.0.0",
     "measured": "^1.0.0",
     "mime-types": "^2.0.1",
     "mkdirp": "^0.5.0",
@@ -44,6 +44,6 @@
   },
   "devDependencies": {},
   "engines": {
-    "node": "~0.8.0 || >=0.9.12"
+    "node": ">=4.0.0"
   }
 }