hlsrecord 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #!/usr/bin/env node
  2. /* eslint-disable no-process-exit */
  3. "use strict";
  4. // record a live hls-stream storing an on-demand ready version
  5. var fs = require('fs'),
  6. path = require('path');
  7. var nopt = require('noptify/node_modules/nopt');
  8. var HlsSegmentReader = require('hls-segment-reader');
  9. var recorder = require('../lib/recorder');
  10. function DateValue(){}
  11. nopt.typeDefs[DateValue] = { type: DateValue, validate: function (data, key, val) {
  12. var date;
  13. if (val === 'now') val = '+0';
  14. if (val.length && (val[0] === '+' || val[0] === '-')) {
  15. date = new Date(Math.round(new Date().getTime() / 1000 + parseInt(val, 10)) * 1000);
  16. } else if (parseInt(val, 10) == val) {
  17. date = new Date(parseInt(val, 10) * 1000);
  18. } else {
  19. date = new Date(val);
  20. }
  21. if (!date) return false;
  22. data[key] = date;
  23. }};
  24. function HexValue(){}
  25. nopt.typeDefs[HexValue] = { type: HexValue, validate: function (data, key, val) {
  26. console.log('!', data, key, val)
  27. data[key] = new Buffer(val, 'hex');
  28. }};
  29. var hlsrecord = require('noptify')(process.argv, { program: 'hlsrecord <url>' });
  30. hlsrecord.version(require('../package').version)
  31. .option('collect', '-C', 'Collect output segments to a single file', Boolean)
  32. .option('output', '-o', 'Output directory', path)
  33. .option('create-dir', '-c', 'Explicitly create output dir', Boolean)
  34. .option('begin-date', '-b', 'Start recording at', DateValue)
  35. .option('end-date', '-e', 'Stop recording at', DateValue)
  36. .option('start-offset', '-s', 'Playback start time offset in seconds', Number)
  37. .option('create-dir', '-c', 'Explicitly create output dir', Boolean)
  38. .option('extension', 'Preserve specified vendor extension', Array)
  39. .option('segment-extension', 'Preserve specified vendor segment extension', Array)
  40. // .option('-a, --user-agent <string>', 'HTTP User-Agent')
  41. // .option('-f, --full', 'record all variants')
  42. .parse(process.argv);
  43. var options = hlsrecord.nopt;
  44. var src = options.argv.remain[0];
  45. if (!src) {
  46. hlsrecord.help();
  47. process.exit(-1);
  48. }
  49. var outDir = options.output || 'stream';
  50. if (options['create-dir'])
  51. fs.mkdirSync(outDir);
  52. if (options['begin-date'])
  53. console.log('fetching from:', options['begin-date']);
  54. if (options['end-date'])
  55. console.log('fetching until:', options['end-date']);
  56. var extensions = {};
  57. (options.extension || []).forEach(function(ext) {
  58. extensions[ext] = false;
  59. });
  60. (options['segment-extension'] || []).forEach(function(ext) {
  61. extensions[ext] = true;
  62. });
  63. var readerOptions = {
  64. withData: true,
  65. fullStream: !options['begin-date'],
  66. startDate: options['begin-date'],
  67. stopDate: options['end-date'],
  68. maxStallTime: 5 * 60 * 1000,
  69. extensions: extensions,
  70. highWaterMark: 0,
  71. };
  72. function createReader(src) {
  73. var r = new HlsSegmentReader(src, readerOptions);
  74. r.on('error', function(err) {
  75. console.error('reader error', err);
  76. });
  77. return r;
  78. }
  79. var rdr = createReader(src);
  80. recorder(rdr, outDir, { subreader:createReader, startOffset: options['start-offset'], collect: options.collect }).start();