sp-broadcaster
Version:
I'm the container that runs Streamplace broadcasts!
140 lines (120 loc) • 4.64 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _spClient = require("sp-client");
var _spClient2 = _interopRequireDefault(_spClient);
var _winston = require("winston");
var _winston2 = _interopRequireDefault(_winston);
var _debug = require("debug");
var _debug2 = _interopRequireDefault(_debug);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var POD_IP = _spClient.config.require("POD_IP");
var STREAM_UPDATE_INTERVAL = 3000;
var log = (0, _debug2.default)("sp:file-stream-manager");
var FileStreamManager = function () {
function FileStreamManager(_ref) {
var _this = this;
var fileId = _ref.fileId;
_classCallCheck(this, FileStreamManager);
this.fileId = fileId;
this.S3_ACCESS_KEY_ID = _spClient.config.require("S3_ACCESS_KEY_ID");
this.S3_SECRET_ACCESS_KEY = _spClient.config.require("S3_SECRET_ACCESS_KEY");
this.tcpEgress = (0, _spClient.tcpEgressStream)();
this.constantFps = (0, _spClient.constantFpsStream)({ fps: 30 });
this.constantFps.on("pts", function (_ref2) {
var pts = _ref2.pts;
_this.currentPts = pts;
});
this.constantFps.pipe(this.tcpEgress, { end: false });
this.tcpEgress.getPort().then(function (port) {
return _spClient2.default.streams.create({
source: {
kind: "File",
id: _this.fileId
},
timestamp: {
time: Date.now(),
pts: 0
},
format: "mpegts",
url: "tcp://" + POD_IP + ":" + port,
streams: [{
media: "video"
}, {
media: "audio"
}]
});
}).then(function (stream) {
_this.stream = stream;
_this.interval = setInterval(function () {
_this.updateStream();
}, STREAM_UPDATE_INTERVAL);
_this.streamFile();
}).catch(function (err) {
_winston2.default.error("Error setting up file-stream-manager", err);
});
}
_createClass(FileStreamManager, [{
key: "streamFile",
value: function streamFile() {
var _this2 = this;
return _spClient2.default.files.findOne(this.fileId).then(function (file) {
return (0, _spClient.fileInputStream)({
accessKeyId: _this2.S3_ACCESS_KEY_ID,
secretAccessKey: _this2.S3_SECRET_ACCESS_KEY,
host: file.host,
bucket: file.bucket,
prefix: file.id
});
}).then(function (fileInput) {
_this2.fileStream = fileInput;
_winston2.default.info("File " + _this2.fileId + " is looping.");
_this2.fileInput = fileInput;
_this2.fileInput.pipe(_this2.constantFps, { end: false });
_this2.fileInput.on("end", function () {
log("fileInput ended");
_this2.currentPts = 0;
_this2.updateStream();
_this2.streamFile();
});
}).catch(function (err) {
_winston2.default.error("Error streaming file " + _this2.fileId, err);
throw err;
});
}
}, {
key: "updateStream",
value: function updateStream() {
if (!this.currentPts) {
return;
}
_spClient2.default.streams.update(this.stream.id, {
timestamp: {
time: Date.now(),
pts: this.currentPts
}
}).catch(function (err) {
return _winston2.default.error(err);
});
}
}, {
key: "shutdown",
value: function shutdown() {
this.fileStream && this.rtmpInput.end();
if (this.interval) {
clearInterval(this.interval);
}
if (this.stream) {
_spClient2.default.streams.delete(this.stream.id).catch(function (err) {
_winston2.default.error("Error cleaning up file input stream", err);
});
}
}
}]);
return FileStreamManager;
}();
exports.default = FileStreamManager;
//# sourceMappingURL=file-stream-manager.js.map