hls-uploader.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. 'use strict';
  2. const Assert = require('assert');
  3. const Fs = require('fs');
  4. const Path = require('path');
  5. const Url = require('url');
  6. const Util = require('util');
  7. const Mkdirp = require('mkdirp');
  8. const Pati = require('pati');
  9. const WriteFileAtomic = require('write-file-atomic');
  10. const internals = {};
  11. internals.fs = {
  12. appendFile: Util.promisify(Fs.appendFile),
  13. writeFile: Util.promisify(WriteFileAtomic)
  14. };
  15. class HlsUploader {
  16. constructor(targetUri, options) {
  17. Assert.equal(Url.parse(targetUri).protocol, null);
  18. this.targetUri = targetUri;
  19. this.indexName = options.indexName || 'index.m3u8';
  20. this.collect = !!options.collect;
  21. // State
  22. this.lastIndexString = '';
  23. this.segmentBytes = 0;
  24. // TODO: make async?
  25. if (!Fs.existsSync(this.targetUri)) {
  26. Mkdirp.sync(this.targetUri);
  27. }
  28. }
  29. async pushSegment(stream, name) {
  30. const target = this.prepareTargetStream(name);
  31. stream.pipe(target);
  32. const dispatcher = new Pati.EventDispatcher(stream);
  33. dispatcher.on('end', Pati.EventDispatcher.end);
  34. let bytesWritten = 0;
  35. dispatcher.on('data', (chunk) => {
  36. bytesWritten += +chunk.length;
  37. });
  38. try {
  39. // TODO: handle target errors & wait for end?
  40. await dispatcher.finish();
  41. return bytesWritten;
  42. }
  43. finally {
  44. this.segmentBytes += bytesWritten;
  45. }
  46. }
  47. prepareTargetStream(name) {
  48. const append = this.collect && this.segmentBytes !== 0;
  49. return Fs.createWriteStream(Path.join(this.targetUri, name), { flags: append ? 'a' : 'w' });
  50. }
  51. flushIndex(index) {
  52. const indexString = index.toString().trim();
  53. let appendString;
  54. if (this.lastIndexString && indexString.startsWith(this.lastIndexString)) {
  55. const lastLength = this.lastIndexString.length;
  56. appendString = indexString.substr(lastLength);
  57. }
  58. this.lastIndexString = indexString;
  59. if (appendString) {
  60. return internals.fs.appendFile(Path.join(this.targetUri, this.indexName), appendString);
  61. }
  62. else {
  63. return internals.fs.writeFile(Path.join(this.targetUri, this.indexName), indexString);
  64. }
  65. }
  66. };
  67. module.exports = HlsUploader;