@gabrielmaialva33/discord-video-stream
Advanced tools
Comparing version 0.1.1 to 0.1.2
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.GatewayOpCodes = void 0; | ||
var GatewayOpCodes; | ||
export var GatewayOpCodes; | ||
(function (GatewayOpCodes) { | ||
@@ -40,2 +37,2 @@ GatewayOpCodes[GatewayOpCodes["DISPATCH"] = 0] = "DISPATCH"; | ||
GatewayOpCodes[GatewayOpCodes["SEARCH_RECENT_MEMBERS"] = 35] = "SEARCH_RECENT_MEMBERS"; | ||
})(GatewayOpCodes || (exports.GatewayOpCodes = GatewayOpCodes = {})); | ||
})(GatewayOpCodes || (GatewayOpCodes = {})); |
@@ -1,21 +0,5 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("#src/client/packet/index"), exports); | ||
__exportStar(require("#src/client/voice/index"), exports); | ||
__exportStar(require("#src/client/streamer"), exports); | ||
__exportStar(require("#src/client/gateway_op_codes"), exports); | ||
__exportStar(require("#src/client/stream_opts"), exports); | ||
export * from '#src/client/packet/index'; | ||
export * from '#src/client/voice/index'; | ||
export * from '#src/client/streamer'; | ||
export * from '#src/client/gateway_op_codes'; | ||
export * from '#src/client/stream_opts'; |
@@ -1,2 +0,2 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { MediaUdp } from '#src/client/voice/media_udp'; | ||
@@ -3,0 +3,0 @@ import { BaseMediaPacketizer } from '#src/client/packet/base_media_packetizer'; |
@@ -1,7 +0,4 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AudioPacketizer = void 0; | ||
const base_media_packetizer_1 = require("#src/client/packet/base_media_packetizer"); | ||
import { BaseMediaPacketizer } from '#src/client/packet/base_media_packetizer'; | ||
const FRAME_SIZE = (48000 / 100) * 2; | ||
class AudioPacketizer extends base_media_packetizer_1.BaseMediaPacketizer { | ||
export class AudioPacketizer extends BaseMediaPacketizer { | ||
constructor(connection) { | ||
@@ -27,2 +24,1 @@ super(connection, 0x78); | ||
} | ||
exports.AudioPacketizer = AudioPacketizer; |
@@ -1,2 +0,2 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { MediaUdp } from '#src/client/voice/media_udp'; | ||
@@ -3,0 +3,0 @@ export declare const MAX_INT16BIT: number; |
@@ -1,9 +0,6 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.BaseMediaPacketizer = exports.MAX_INT32BIT = exports.MAX_INT16BIT = void 0; | ||
const libsodium_wrappers_1 = require("libsodium-wrappers"); | ||
exports.MAX_INT16BIT = 2 ** 16; | ||
exports.MAX_INT32BIT = 2 ** 32; | ||
import { crypto_secretbox_easy } from 'libsodium-wrappers'; | ||
export const MAX_INT16BIT = 2 ** 16; | ||
export const MAX_INT32BIT = 2 ** 32; | ||
const ntpEpoch = new Date('Jan 01 1900 GMT').getTime(); | ||
class BaseMediaPacketizer { | ||
export class BaseMediaPacketizer { | ||
_payloadType; | ||
@@ -63,3 +60,3 @@ _sequence; | ||
this._totalPackets = this._totalPackets + packetsSent; | ||
this._totalBytes = (this._totalBytes + bytesSent) % exports.MAX_INT32BIT; | ||
this._totalBytes = (this._totalBytes + bytesSent) % MAX_INT32BIT; | ||
// Not using modulo here, since the number of packet sent might not be | ||
@@ -93,7 +90,7 @@ // exactly a multiple of the interval | ||
getNewSequence() { | ||
this._sequence = (this._sequence + 1) % exports.MAX_INT16BIT; | ||
this._sequence = (this._sequence + 1) % MAX_INT16BIT; | ||
return this._sequence; | ||
} | ||
incrementTimestamp(incrementBy) { | ||
this._timestamp = (this._timestamp + incrementBy) % exports.MAX_INT32BIT; | ||
this._timestamp = (this._timestamp + incrementBy) % MAX_INT32BIT; | ||
} | ||
@@ -125,7 +122,7 @@ makeRtpHeader(isLastPacket = true) { | ||
const ntpTimestampMsw = Math.floor(ntpTimestamp); | ||
const ntpTimestampLsw = Math.round((ntpTimestamp - ntpTimestampMsw) * exports.MAX_INT32BIT); | ||
const ntpTimestampLsw = Math.round((ntpTimestamp - ntpTimestampMsw) * MAX_INT32BIT); | ||
senderReport.writeUInt32BE(ntpTimestampMsw, 0); | ||
senderReport.writeUInt32BE(ntpTimestampLsw, 4); | ||
senderReport.writeUInt32BE(this._timestamp, 8); | ||
senderReport.writeUInt32BE(this._totalPackets % exports.MAX_INT32BIT, 12); | ||
senderReport.writeUInt32BE(this._totalPackets % MAX_INT32BIT, 12); | ||
senderReport.writeUInt32BE(this._totalBytes, 16); | ||
@@ -135,3 +132,3 @@ const nonceBuffer = this._mediaUdp.getNewNonceBuffer(); | ||
packetHeader, | ||
(0, libsodium_wrappers_1.crypto_secretbox_easy)(senderReport, nonceBuffer, this._mediaUdp.mediaConnection.secretkey), | ||
crypto_secretbox_easy(senderReport, nonceBuffer, this._mediaUdp.mediaConnection.secretkey), | ||
nonceBuffer.subarray(0, 4), | ||
@@ -187,5 +184,4 @@ ]); | ||
encryptData(message, nonceBuffer) { | ||
return (0, libsodium_wrappers_1.crypto_secretbox_easy)(message, nonceBuffer, this._mediaUdp.mediaConnection.secretkey); | ||
return crypto_secretbox_easy(message, nonceBuffer, this._mediaUdp.mediaConnection.secretkey); | ||
} | ||
} | ||
exports.BaseMediaPacketizer = BaseMediaPacketizer; |
@@ -1,20 +0,4 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("#src/client/packet/base_media_packetizer"), exports); | ||
__exportStar(require("#src/client/packet/audio_packetizer"), exports); | ||
__exportStar(require("#src/client/packet/video_packetizer_vp8"), exports); | ||
__exportStar(require("#src/client/packet/video_packetizer_annex_b"), exports); | ||
export * from '#src/client/packet/base_media_packetizer'; | ||
export * from '#src/client/packet/audio_packetizer'; | ||
export * from '#src/client/packet/video_packetizer_vp8'; | ||
export * from '#src/client/packet/video_packetizer_annex_b'; |
@@ -1,2 +0,2 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { MediaUdp } from '#src/client/voice/media_udp'; | ||
@@ -3,0 +3,0 @@ import { BaseMediaPacketizer } from '#src/client/packet/base_media_packetizer'; |
@@ -1,7 +0,4 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.VideoPacketizerH265 = exports.VideoPacketizerH264 = void 0; | ||
const stream_opts_1 = require("#src/client/stream_opts"); | ||
const base_media_packetizer_1 = require("#src/client/packet/base_media_packetizer"); | ||
const annex_bhelper_1 = require("#src/client/processing/annex_bhelper"); | ||
import { streamOpts } from '#src/client/stream_opts'; | ||
import { BaseMediaPacketizer } from '#src/client/packet/base_media_packetizer'; | ||
import { H264Helpers, H265Helpers } from '#src/client/processing/annex_bhelper'; | ||
/** | ||
@@ -56,7 +53,7 @@ * Annex B format | ||
*/ | ||
class VideoPacketizerAnnexB extends base_media_packetizer_1.BaseMediaPacketizer { | ||
class VideoPacketizerAnnexB extends BaseMediaPacketizer { | ||
_nalFunctions; | ||
constructor(connection) { | ||
super(connection, 0x65, true); | ||
this.srInterval = 5 * (stream_opts_1.streamOpts.fps || 30) * 3; // ~5 seconds, assuming ~3 packets per frame | ||
this.srInterval = 5 * (streamOpts.fps || 30) * 3; // ~5 seconds, assuming ~3 packets per frame | ||
} | ||
@@ -132,3 +129,3 @@ /** | ||
// video RTP packet timestamp incremental value = 90,000Hz / fps | ||
this.incrementTimestamp(90000 / (stream_opts_1.streamOpts.fps || 30)); | ||
this.incrementTimestamp(90000 / (streamOpts.fps || 30)); | ||
} | ||
@@ -140,6 +137,6 @@ makeFragmentationUnitHeader(isFirstPacket, isLastPacket, naluHeader) { | ||
} | ||
class VideoPacketizerH264 extends VideoPacketizerAnnexB { | ||
export class VideoPacketizerH264 extends VideoPacketizerAnnexB { | ||
constructor(connection) { | ||
super(connection); | ||
this._nalFunctions = annex_bhelper_1.H264Helpers; | ||
this._nalFunctions = H264Helpers; | ||
} | ||
@@ -179,3 +176,3 @@ /** | ||
const fuPayloadHeader = Buffer.alloc(2); | ||
const nalType = annex_bhelper_1.H264Helpers.getUnitType(naluHeader); | ||
const nalType = H264Helpers.getUnitType(naluHeader); | ||
const fnri = nal0 & 0xe0; | ||
@@ -197,7 +194,6 @@ // set fu indicator | ||
} | ||
exports.VideoPacketizerH264 = VideoPacketizerH264; | ||
class VideoPacketizerH265 extends VideoPacketizerAnnexB { | ||
export class VideoPacketizerH265 extends VideoPacketizerAnnexB { | ||
constructor(connection) { | ||
super(connection); | ||
this._nalFunctions = annex_bhelper_1.H265Helpers; | ||
this._nalFunctions = H265Helpers; | ||
} | ||
@@ -236,3 +232,3 @@ /** | ||
naluHeader.copy(fuIndicatorHeader); | ||
const nalType = annex_bhelper_1.H265Helpers.getUnitType(naluHeader); | ||
const nalType = H265Helpers.getUnitType(naluHeader); | ||
// clear NAL type and set it to 49 | ||
@@ -253,2 +249,1 @@ fuIndicatorHeader[0] = (fuIndicatorHeader[0] & 0b10000001) | (49 << 1); | ||
} | ||
exports.VideoPacketizerH265 = VideoPacketizerH265; |
@@ -1,4 +0,4 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { BaseMediaPacketizer } from '#src/client/index'; | ||
import { MediaUdp } from '#src/client/voice/index'; | ||
import { MediaUdp } from '#src/client/index'; | ||
/** | ||
@@ -5,0 +5,0 @@ * VP8 payload format |
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.VideoPacketizerVP8 = void 0; | ||
const index_1 = require("#src/client/index"); | ||
import { BaseMediaPacketizer, MAX_INT16BIT, streamOpts } from '#src/client/index'; | ||
/** | ||
@@ -9,3 +6,3 @@ * VP8 payload format | ||
*/ | ||
class VideoPacketizerVP8 extends index_1.BaseMediaPacketizer { | ||
export class VideoPacketizerVP8 extends BaseMediaPacketizer { | ||
_pictureId; | ||
@@ -15,3 +12,3 @@ constructor(connection) { | ||
this._pictureId = 0; | ||
this.srInterval = 5 * (index_1.streamOpts.fps || 30) * 3; // ~5 seconds, assuming ~3 packets per frame | ||
this.srInterval = 5 * (streamOpts.fps || 30) * 3; // ~5 seconds, assuming ~3 packets per frame | ||
} | ||
@@ -45,7 +42,7 @@ sendFrame(frame) { | ||
// video RTP packet timestamp incremental value = 90,000Hz / fps | ||
this.incrementTimestamp(90000 / (index_1.streamOpts.fps || 30)); | ||
this.incrementTimestamp(90000 / (streamOpts.fps || 30)); | ||
this.incrementPictureId(); | ||
} | ||
incrementPictureId() { | ||
this._pictureId = (this._pictureId + 1) % index_1.MAX_INT16BIT; | ||
this._pictureId = (this._pictureId + 1) % MAX_INT16BIT; | ||
} | ||
@@ -68,2 +65,1 @@ makeChunk(frameData, isFirstPacket) { | ||
} | ||
exports.VideoPacketizerVP8 = VideoPacketizerVP8; |
@@ -1,2 +0,2 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" resolution-mode="require"/> | ||
export declare enum H264NalUnitTypes { | ||
@@ -3,0 +3,0 @@ Unspecified = 0, |
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.H265Helpers = exports.H264Helpers = exports.H265NalUnitTypes = exports.H264NalUnitTypes = void 0; | ||
var H264NalUnitTypes; | ||
export var H264NalUnitTypes; | ||
(function (H264NalUnitTypes) { | ||
@@ -22,4 +19,4 @@ H264NalUnitTypes[H264NalUnitTypes["Unspecified"] = 0] = "Unspecified"; | ||
H264NalUnitTypes[H264NalUnitTypes["SubsetSPS"] = 15] = "SubsetSPS"; | ||
})(H264NalUnitTypes || (exports.H264NalUnitTypes = H264NalUnitTypes = {})); | ||
var H265NalUnitTypes; | ||
})(H264NalUnitTypes || (H264NalUnitTypes = {})); | ||
export var H265NalUnitTypes; | ||
(function (H265NalUnitTypes) { | ||
@@ -90,4 +87,4 @@ H265NalUnitTypes[H265NalUnitTypes["TRAIL_N"] = 0] = "TRAIL_N"; | ||
H265NalUnitTypes[H265NalUnitTypes["UNSPEC63"] = 63] = "UNSPEC63"; | ||
})(H265NalUnitTypes || (exports.H265NalUnitTypes = H265NalUnitTypes = {})); | ||
exports.H264Helpers = { | ||
})(H265NalUnitTypes || (H265NalUnitTypes = {})); | ||
export const H264Helpers = { | ||
getUnitType(frame) { | ||
@@ -103,3 +100,3 @@ return frame[0] & 0x1f; | ||
}; | ||
exports.H265Helpers = { | ||
export const H265Helpers = { | ||
getUnitType(frame) { | ||
@@ -106,0 +103,0 @@ return (frame[0] >> 1) & 0x3f; |
@@ -1,3 +0,3 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
/// <reference types="node" resolution-mode="require"/> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { Transform, TransformCallback } from 'node:stream'; | ||
@@ -4,0 +4,0 @@ import { AnnexBHelpers } from '#src/client/processing/annex_bhelper'; |
@@ -1,6 +0,3 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.H265NalSplitter = exports.H264NalSplitter = void 0; | ||
const node_stream_1 = require("node:stream"); | ||
const annex_bhelper_1 = require("#src/client/processing/annex_bhelper"); | ||
import { Transform } from 'node:stream'; | ||
import { H264Helpers, H264NalUnitTypes, H265Helpers, } from '#src/client/processing/annex_bhelper'; | ||
const emptyBuffer = Buffer.allocUnsafe(0); | ||
@@ -17,3 +14,3 @@ const epbPrefix = Buffer.from([0x00, 0x00, 0x03]); | ||
*/ | ||
class AnnexBNalSplitter extends node_stream_1.Transform { | ||
class AnnexBNalSplitter extends Transform { | ||
_nalFunctions; | ||
@@ -114,9 +111,9 @@ _buffer; | ||
} | ||
class H264NalSplitter extends AnnexBNalSplitter { | ||
export class H264NalSplitter extends AnnexBNalSplitter { | ||
constructor() { | ||
super(); | ||
this._nalFunctions = annex_bhelper_1.H264Helpers; | ||
this._nalFunctions = H264Helpers; | ||
} | ||
removeEpbs(frame, unitType) { | ||
if (unitType === annex_bhelper_1.H264NalUnitTypes.SPS || unitType === annex_bhelper_1.H264NalUnitTypes.SEI) | ||
if (unitType === H264NalUnitTypes.SPS || unitType === H264NalUnitTypes.SEI) | ||
return this.rbsp(frame); | ||
@@ -126,7 +123,6 @@ return frame; | ||
} | ||
exports.H264NalSplitter = H264NalSplitter; | ||
class H265NalSplitter extends AnnexBNalSplitter { | ||
export class H265NalSplitter extends AnnexBNalSplitter { | ||
constructor() { | ||
super(); | ||
this._nalFunctions = annex_bhelper_1.H265Helpers; | ||
this._nalFunctions = H265Helpers; | ||
} | ||
@@ -139,2 +135,1 @@ removeEpbs(frame, _unitType) { | ||
} | ||
exports.H265NalSplitter = H265NalSplitter; |
@@ -1,19 +0,3 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("#src/client/processing/ivf_splitter"), exports); | ||
__exportStar(require("#src/client/processing/annex_bhelper"), exports); | ||
__exportStar(require("#src/client/processing/annex_bnal_splitter"), exports); | ||
export * from '#src/client/processing/ivf_splitter'; | ||
export * from '#src/client/processing/annex_bhelper'; | ||
export * from '#src/client/processing/annex_bnal_splitter'; |
@@ -1,3 +0,3 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
/// <reference types="node" resolution-mode="require"/> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { Transform, TransformCallback } from 'node:stream'; | ||
@@ -4,0 +4,0 @@ type IvfHeader = { |
@@ -1,9 +0,3 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.IvfTransformer = exports.getFrameDelayInMilliseconds = exports.readIvfFile = exports.getFrameFromIvf = void 0; | ||
const node_fs_1 = __importDefault(require("node:fs")); | ||
const node_stream_1 = require("node:stream"); | ||
import fs from 'node:fs'; | ||
import { Transform } from 'node:stream'; | ||
/* | ||
@@ -13,3 +7,3 @@ ** Transform stream to transform file stream into ivf file | ||
*/ | ||
class IvfTransformer extends node_stream_1.Transform { | ||
class IvfTransformer extends Transform { | ||
headerSize; | ||
@@ -97,5 +91,4 @@ frameHeaderSize; | ||
} | ||
exports.IvfTransformer = IvfTransformer; | ||
async function readIvfFile(filepath) { | ||
const inputStream = node_fs_1.default.createReadStream(filepath); | ||
const inputStream = fs.createReadStream(filepath); | ||
const stream = new IvfTransformer({ fullframe: true }); | ||
@@ -123,3 +116,2 @@ inputStream.pipe(stream); | ||
} | ||
exports.readIvfFile = readIvfFile; | ||
// get frame, starts at one | ||
@@ -149,6 +141,5 @@ function getFrameFromIvf(file, framenum = 1) { | ||
} | ||
exports.getFrameFromIvf = getFrameFromIvf; | ||
function getFrameDelayInMilliseconds(file) { | ||
return (file.timeNumerator / file.timeDenominator) * 1000; | ||
} | ||
exports.getFrameDelayInMilliseconds = getFrameDelayInMilliseconds; | ||
export { getFrameFromIvf, readIvfFile, getFrameDelayInMilliseconds, IvfTransformer }; |
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.setStreamOpts = exports.streamOpts = void 0; | ||
exports.streamOpts = { | ||
export const streamOpts = { | ||
width: 1080, | ||
@@ -13,11 +10,10 @@ height: 720, | ||
}; | ||
const setStreamOpts = (opts) => { | ||
exports.streamOpts.width = opts.width ?? exports.streamOpts.width; | ||
exports.streamOpts.height = opts.height ?? exports.streamOpts.height; | ||
exports.streamOpts.fps = opts.fps ?? exports.streamOpts.fps; | ||
exports.streamOpts.bitrateKbps = opts.bitrateKbps ?? exports.streamOpts.bitrateKbps; | ||
exports.streamOpts.maxBitrateKbps = opts.maxBitrateKbps ?? exports.streamOpts.maxBitrateKbps; | ||
exports.streamOpts.hardware_acceleration = opts.hardware_acceleration ?? exports.streamOpts.hardware_acceleration; | ||
exports.streamOpts.video_codec = opts.video_codec ?? exports.streamOpts.video_codec; | ||
export const setStreamOpts = (opts) => { | ||
streamOpts.width = opts.width ?? streamOpts.width; | ||
streamOpts.height = opts.height ?? streamOpts.height; | ||
streamOpts.fps = opts.fps ?? streamOpts.fps; | ||
streamOpts.bitrateKbps = opts.bitrateKbps ?? streamOpts.bitrateKbps; | ||
streamOpts.maxBitrateKbps = opts.maxBitrateKbps ?? streamOpts.maxBitrateKbps; | ||
streamOpts.hardware_acceleration = opts.hardware_acceleration ?? streamOpts.hardware_acceleration; | ||
streamOpts.video_codec = opts.video_codec ?? streamOpts.video_codec; | ||
}; | ||
exports.setStreamOpts = setStreamOpts; |
@@ -1,7 +0,4 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Streamer = void 0; | ||
const index_1 = require("#src/client/voice/index"); | ||
const gateway_op_codes_1 = require("#src/client/gateway_op_codes"); | ||
class Streamer { | ||
import { StreamConnection, VoiceConnection } from '#src/client/voice/index'; | ||
import { GatewayOpCodes } from '#src/client/gateway_op_codes'; | ||
export class Streamer { | ||
constructor(client) { | ||
@@ -31,3 +28,3 @@ this._client = client; | ||
return new Promise((resolve, _reject) => { | ||
this._voiceConnection = new index_1.VoiceConnection(guild_id, this.client.user.id, channel_id, (voiceUdp) => { | ||
this._voiceConnection = new VoiceConnection(guild_id, this.client.user.id, channel_id, (voiceUdp) => { | ||
resolve(voiceUdp); | ||
@@ -43,3 +40,3 @@ }); | ||
this.signalStream(this.voiceConnection.guildId, this.voiceConnection.channelId); | ||
this.voiceConnection.streamConnection = new index_1.StreamConnection(this.voiceConnection.guildId, this.client.user.id, this.voiceConnection.channelId, (voiceUdp) => { | ||
this.voiceConnection.streamConnection = new StreamConnection(this.voiceConnection.guildId, this.client.user.id, this.voiceConnection.channelId, (voiceUdp) => { | ||
resolve(voiceUdp); | ||
@@ -63,3 +60,3 @@ }); | ||
signalVideo(guild_id, channel_id, video_enabled) { | ||
this.sendOpcode(gateway_op_codes_1.GatewayOpCodes.VOICE_STATE_UPDATE, { | ||
this.sendOpcode(GatewayOpCodes.VOICE_STATE_UPDATE, { | ||
guild_id, | ||
@@ -73,3 +70,3 @@ channel_id, | ||
signalStream(guild_id, channel_id) { | ||
this.sendOpcode(gateway_op_codes_1.GatewayOpCodes.STREAM_CREATE, { | ||
this.sendOpcode(GatewayOpCodes.STREAM_CREATE, { | ||
type: 'guild', | ||
@@ -80,3 +77,3 @@ guild_id, | ||
}); | ||
this.sendOpcode(gateway_op_codes_1.GatewayOpCodes.STREAM_SET_PAUSED, { | ||
this.sendOpcode(GatewayOpCodes.STREAM_SET_PAUSED, { | ||
stream_key: `guild:${guild_id}:${channel_id}:${this.client.user.id}`, | ||
@@ -87,3 +84,3 @@ paused: false, | ||
signalStopStream(guild_id, channel_id) { | ||
this.sendOpcode(gateway_op_codes_1.GatewayOpCodes.STREAM_DELETE, { | ||
this.sendOpcode(GatewayOpCodes.STREAM_DELETE, { | ||
stream_key: `guild:${guild_id}:${channel_id}:${this.client.user.id}`, | ||
@@ -93,3 +90,3 @@ }); | ||
signalLeaveVoice() { | ||
this.sendOpcode(gateway_op_codes_1.GatewayOpCodes.VOICE_STATE_UPDATE, { | ||
this.sendOpcode(GatewayOpCodes.VOICE_STATE_UPDATE, { | ||
guild_id: null, | ||
@@ -143,2 +140,1 @@ channel_id: null, | ||
} | ||
exports.Streamer = Streamer; |
@@ -1,13 +0,7 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.BaseMediaConnection = void 0; | ||
const ws_1 = __importDefault(require("ws")); | ||
const media_udp_1 = require("#src/client/voice/media_udp"); | ||
const voice_op_codes_1 = require("#src/client/voice/voice_op_codes"); | ||
const index_1 = require("#src/client/index"); | ||
const utils_1 = require("#src/utils"); | ||
class BaseMediaConnection { | ||
import WebSocket from 'ws'; | ||
import { MediaUdp } from '#src/client/voice/media_udp'; | ||
import { VoiceOpCodes } from '#src/client/voice/voice_op_codes'; | ||
import { streamOpts } from '#src/client/index'; | ||
import { normalizeVideoCodec } from '#src/utils'; | ||
export class BaseMediaConnection { | ||
udp; | ||
@@ -41,3 +35,3 @@ guildId; | ||
// make udp client | ||
this.udp = new media_udp_1.MediaUdp(this); | ||
this.udp = new MediaUdp(this); | ||
this.guildId = guildId; | ||
@@ -74,3 +68,3 @@ this.channelId = channelId; | ||
this.status.started = true; | ||
this.ws = new ws_1.default('wss://' + this.server + '/?v=7', { | ||
this.ws = new WebSocket('wss://' + this.server + '/?v=7', { | ||
followRedirects: true, | ||
@@ -121,3 +115,3 @@ }); | ||
const { op, d } = JSON.parse(data); | ||
if (op === voice_op_codes_1.VoiceOpCodes.READY) { | ||
if (op === VoiceOpCodes.READY) { | ||
// ready | ||
@@ -131,16 +125,16 @@ this.handleReady(d); | ||
} | ||
else if (op === voice_op_codes_1.VoiceOpCodes.HELLO) { | ||
else if (op === VoiceOpCodes.HELLO) { | ||
this.setupHeartbeat(d.heartbeat_interval); | ||
} | ||
else if (op === voice_op_codes_1.VoiceOpCodes.SELECT_PROTOCOL_ACK) { | ||
else if (op === VoiceOpCodes.SELECT_PROTOCOL_ACK) { | ||
// session description | ||
this.handleSession(d); | ||
} | ||
else if (op === voice_op_codes_1.VoiceOpCodes.SPEAKING) { | ||
else if (op === VoiceOpCodes.SPEAKING) { | ||
// ignore speaking updates | ||
} | ||
else if (op === voice_op_codes_1.VoiceOpCodes.HEARTBEAT_ACK) { | ||
else if (op === VoiceOpCodes.HEARTBEAT_ACK) { | ||
// ignore heartbeat acknowledgements | ||
} | ||
else if (op === voice_op_codes_1.VoiceOpCodes.RESUMED) { | ||
else if (op === VoiceOpCodes.RESUMED) { | ||
this.status.started = true; | ||
@@ -159,3 +153,3 @@ this.udp.ready = true; | ||
this.interval = setInterval(() => { | ||
this.sendOpcode(voice_op_codes_1.VoiceOpCodes.HEARTBEAT, 42069); | ||
this.sendOpcode(VoiceOpCodes.HEARTBEAT, 42069); | ||
}, interval); | ||
@@ -173,3 +167,3 @@ } | ||
identify() { | ||
this.sendOpcode(voice_op_codes_1.VoiceOpCodes.IDENTIFY, { | ||
this.sendOpcode(VoiceOpCodes.IDENTIFY, { | ||
server_id: this.serverId, | ||
@@ -184,3 +178,3 @@ user_id: this.botId, | ||
resume() { | ||
this.sendOpcode(voice_op_codes_1.VoiceOpCodes.RESUME, { | ||
this.sendOpcode(VoiceOpCodes.RESUME, { | ||
server_id: this.serverId, | ||
@@ -197,3 +191,3 @@ session_id: this.session_id, | ||
setProtocols() { | ||
this.sendOpcode(voice_op_codes_1.VoiceOpCodes.SELECT_PROTOCOL, { | ||
this.sendOpcode(VoiceOpCodes.SELECT_PROTOCOL, { | ||
protocol: 'udp', | ||
@@ -203,3 +197,3 @@ codecs: [ | ||
{ | ||
name: (0, utils_1.normalizeVideoCodec)(index_1.streamOpts.video_codec || 'h264'), | ||
name: normalizeVideoCodec(streamOpts.video_codec || 'h264'), | ||
type: 'video', | ||
@@ -228,3 +222,3 @@ priority: 1000, | ||
setVideoStatus(bool) { | ||
this.sendOpcode(voice_op_codes_1.VoiceOpCodes.VIDEO, { | ||
this.sendOpcode(VoiceOpCodes.VIDEO, { | ||
audio_ssrc: this.ssrc, | ||
@@ -241,8 +235,8 @@ video_ssrc: bool ? this.videoSsrc : 0, | ||
rtx_ssrc: bool ? this.rtxSsrc : 0, | ||
max_bitrate: (index_1.streamOpts.maxBitrateKbps || 4000) * 1000, | ||
max_framerate: index_1.streamOpts.fps, | ||
max_bitrate: (streamOpts.maxBitrateKbps || 4000) * 1000, | ||
max_framerate: streamOpts.fps, | ||
max_resolution: { | ||
type: 'fixed', | ||
width: index_1.streamOpts.width, | ||
height: index_1.streamOpts.height, | ||
width: streamOpts.width, | ||
height: streamOpts.height, | ||
}, | ||
@@ -258,3 +252,3 @@ }, | ||
setSpeaking(speaking) { | ||
this.sendOpcode(voice_op_codes_1.VoiceOpCodes.SPEAKING, { | ||
this.sendOpcode(VoiceOpCodes.SPEAKING, { | ||
delay: 0, | ||
@@ -276,2 +270,1 @@ speaking: speaking ? 1 : 0, | ||
} | ||
exports.BaseMediaConnection = BaseMediaConnection; |
@@ -1,21 +0,5 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("#src/client/voice/voice_connection"), exports); | ||
__exportStar(require("#src/client/voice/voice_op_codes"), exports); | ||
__exportStar(require("#src/client/voice/media_udp"), exports); | ||
__exportStar(require("#src/client/voice/stream_connection"), exports); | ||
__exportStar(require("#src/client/voice/base_media_connection"), exports); | ||
export * from '#src/client/voice/voice_connection'; | ||
export * from '#src/client/voice/voice_op_codes'; | ||
export * from '#src/client/voice/media_udp'; | ||
export * from '#src/client/voice/stream_connection'; | ||
export * from '#src/client/voice/base_media_connection'; |
@@ -1,2 +0,2 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { BaseMediaConnection, BaseMediaPacketizer } from '#src/client/index'; | ||
@@ -3,0 +3,0 @@ export declare class MediaUdp { |
@@ -1,11 +0,5 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.MediaUdp = void 0; | ||
const node_dgram_1 = __importDefault(require("node:dgram")); | ||
const node_net_1 = require("node:net"); | ||
const index_1 = require("#src/client/index"); | ||
const utils_1 = require("#src/utils"); | ||
import udpCon from 'node:dgram'; | ||
import { isIPv4 } from 'node:net'; | ||
import { AudioPacketizer, MAX_INT32BIT, streamOpts, VideoPacketizerH264, VideoPacketizerH265, VideoPacketizerVP8, } from '#src/client/index'; | ||
import { normalizeVideoCodec } from '#src/utils'; | ||
// credit to discord.js | ||
@@ -15,3 +9,3 @@ function parseLocalPacket(message) { | ||
const ip = packet.subarray(8, packet.indexOf(0, 8)).toString('utf8'); | ||
if (!(0, node_net_1.isIPv4)(ip)) { | ||
if (!isIPv4(ip)) { | ||
throw new Error('Malformed IP address'); | ||
@@ -22,3 +16,3 @@ } | ||
} | ||
class MediaUdp { | ||
export class MediaUdp { | ||
_nonce; | ||
@@ -31,13 +25,13 @@ _socket; | ||
this._mediaConnection = voiceConnection; | ||
this._audioPacketizer = new index_1.AudioPacketizer(this); | ||
const videoCodec = (0, utils_1.normalizeVideoCodec)(index_1.streamOpts.video_codec || 'H264'); | ||
this._audioPacketizer = new AudioPacketizer(this); | ||
const videoCodec = normalizeVideoCodec(streamOpts.video_codec || 'H264'); | ||
switch (videoCodec) { | ||
case 'H264': | ||
this._videoPacketizer = new index_1.VideoPacketizerH264(this); | ||
this._videoPacketizer = new VideoPacketizerH264(this); | ||
break; | ||
case 'H265': | ||
this._videoPacketizer = new index_1.VideoPacketizerH265(this); | ||
this._videoPacketizer = new VideoPacketizerH265(this); | ||
break; | ||
case 'VP8': | ||
this._videoPacketizer = new index_1.VideoPacketizerVP8(this); | ||
this._videoPacketizer = new VideoPacketizerVP8(this); | ||
break; | ||
@@ -67,3 +61,3 @@ default: | ||
const nonceBuffer = Buffer.alloc(24); | ||
this._nonce = (this._nonce + 1) % index_1.MAX_INT32BIT; | ||
this._nonce = (this._nonce + 1) % MAX_INT32BIT; | ||
nonceBuffer.writeUInt32BE(this._nonce, 0); | ||
@@ -111,3 +105,3 @@ return nonceBuffer; | ||
return new Promise((resolve, reject) => { | ||
this._socket = node_dgram_1.default.createSocket('udp4'); | ||
this._socket = udpCon.createSocket('udp4'); | ||
this._socket.on('error', (error) => { | ||
@@ -146,2 +140,1 @@ console.error('Error connecting to media udp server', error); | ||
} | ||
exports.MediaUdp = MediaUdp; |
@@ -1,7 +0,4 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.StreamConnection = void 0; | ||
const index_1 = require("#src/client/index"); | ||
const voice_op_codes_1 = require("#src/client/voice/voice_op_codes"); | ||
class StreamConnection extends index_1.BaseMediaConnection { | ||
import { BaseMediaConnection } from '#src/client/index'; | ||
import { VoiceOpCodes } from '#src/client/voice/voice_op_codes'; | ||
export class StreamConnection extends BaseMediaConnection { | ||
_streamKey; | ||
@@ -22,3 +19,3 @@ get streamKey() { | ||
setSpeaking(speaking) { | ||
this.sendOpcode(voice_op_codes_1.VoiceOpCodes.SPEAKING, { | ||
this.sendOpcode(VoiceOpCodes.SPEAKING, { | ||
delay: 0, | ||
@@ -30,2 +27,1 @@ speaking: speaking ? 2 : 0, | ||
} | ||
exports.StreamConnection = StreamConnection; |
@@ -1,6 +0,3 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.VoiceConnection = void 0; | ||
const index_1 = require("#src/client/index"); | ||
class VoiceConnection extends index_1.BaseMediaConnection { | ||
import { BaseMediaConnection } from '#src/client/index'; | ||
export class VoiceConnection extends BaseMediaConnection { | ||
streamConnection; | ||
@@ -15,2 +12,1 @@ get serverId() { | ||
} | ||
exports.VoiceConnection = VoiceConnection; |
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.VoiceOpCodes = void 0; | ||
var VoiceOpCodes; | ||
export var VoiceOpCodes; | ||
(function (VoiceOpCodes) { | ||
@@ -25,2 +22,2 @@ VoiceOpCodes[VoiceOpCodes["IDENTIFY"] = 0] = "IDENTIFY"; | ||
VoiceOpCodes[VoiceOpCodes["PLATFORM"] = 20] = "PLATFORM"; | ||
})(VoiceOpCodes || (exports.VoiceOpCodes = VoiceOpCodes = {})); | ||
})(VoiceOpCodes || (VoiceOpCodes = {})); |
@@ -1,19 +0,3 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("#src/client/index"), exports); | ||
__exportStar(require("#src/media/index"), exports); | ||
__exportStar(require("#src/utils"), exports); | ||
export * from '#src/client/index'; | ||
export * from '#src/media/index'; | ||
export * from '#src/utils'; |
@@ -1,5 +0,5 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
/// <reference types="node" resolution-mode="require"/> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { Writable } from 'node:stream'; | ||
import { MediaUdp } from '#src/client/voice/index'; | ||
import { MediaUdp } from '#src/client/index'; | ||
declare class AudioStream extends Writable { | ||
@@ -6,0 +6,0 @@ udp: MediaUdp; |
@@ -1,6 +0,3 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AudioStream = void 0; | ||
const node_stream_1 = require("node:stream"); | ||
class AudioStream extends node_stream_1.Writable { | ||
import { Writable } from 'node:stream'; | ||
class AudioStream extends Writable { | ||
udp; | ||
@@ -34,2 +31,2 @@ count; | ||
} | ||
exports.AudioStream = AudioStream; | ||
export { AudioStream }; |
@@ -1,19 +0,3 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("#src/media/audio_stream"), exports); | ||
__exportStar(require("#src/media/video_stream"), exports); | ||
__exportStar(require("#src/media/stream_livestream_video"), exports); | ||
export * from '#src/media/audio_stream'; | ||
export * from '#src/media/video_stream'; | ||
export * from '#src/media/stream_livestream_video'; |
@@ -1,5 +0,5 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { Readable } from 'node:stream'; | ||
import ffmpeg from 'fluent-ffmpeg'; | ||
import { MediaUdp } from '#src/client/voice/index'; | ||
import { MediaUdp } from '#src/client/index'; | ||
export declare let command: ffmpeg.FfmpegCommand | undefined; | ||
@@ -6,0 +6,0 @@ export declare function streamLivestreamVideo(input: string | Readable, mediaUdp: MediaUdp, includeAudio?: boolean, customHeaders?: Map): Promise<string>; |
@@ -1,23 +0,18 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.inputHasVideo = exports.inputHasAudio = exports.getInputMetadata = exports.streamLivestreamVideo = exports.command = void 0; | ||
const fluent_ffmpeg_1 = __importDefault(require("fluent-ffmpeg")); | ||
const prism_media_1 = __importDefault(require("prism-media")); | ||
const fluent_ffmpeg_multistream_ts_1 = require("@dank074/fluent-ffmpeg-multistream-ts"); | ||
const video_stream_1 = require("#src/media/video_stream"); | ||
const index_1 = require("#src/client/index"); | ||
const index_2 = require("#src/client/processing/index"); | ||
const audio_stream_1 = require("#src/media/audio_stream"); | ||
function streamLivestreamVideo(input, mediaUdp, includeAudio = true, customHeaders) { | ||
import ffmpeg from 'fluent-ffmpeg'; | ||
import prism from 'prism-media'; | ||
import { StreamOutput } from '@dank074/fluent-ffmpeg-multistream-ts'; | ||
import { VideoStream } from '#src/media/video_stream'; | ||
import { streamOpts } from '#src/client/index'; | ||
import { H264NalSplitter, IvfTransformer } from '#src/client/processing/index'; | ||
import { AudioStream } from '#src/media/audio_stream'; | ||
export let command; | ||
export function streamLivestreamVideo(input, mediaUdp, includeAudio = true, customHeaders) { | ||
return new Promise((resolve, reject) => { | ||
const videoStream = new video_stream_1.VideoStream(mediaUdp, index_1.streamOpts.fps); | ||
const videoStream = new VideoStream(mediaUdp, streamOpts.fps); | ||
let videoOutput; | ||
if (index_1.streamOpts.video_codec === 'H264') { | ||
videoOutput = new index_2.H264NalSplitter(); | ||
if (streamOpts.video_codec === 'H264') { | ||
videoOutput = new H264NalSplitter(); | ||
} | ||
else { | ||
videoOutput = new index_2.IvfTransformer(); | ||
videoOutput = new IvfTransformer(); | ||
} | ||
@@ -36,3 +31,3 @@ let headers = { | ||
try { | ||
exports.command = (0, fluent_ffmpeg_1.default)(input) | ||
command = ffmpeg(input) | ||
.addOption('-loglevel', '0') | ||
@@ -42,17 +37,17 @@ .addOption('-fflags', 'nobuffer') | ||
.on('end', () => { | ||
exports.command = undefined; | ||
command = undefined; | ||
resolve('video ended'); | ||
}) | ||
.on('error', (err, _stdout, _stderr) => { | ||
exports.command = undefined; | ||
command = undefined; | ||
reject('cannot play video ' + err.message); | ||
}) | ||
.on('stderr', console.error); | ||
if (index_1.streamOpts.video_codec === 'VP8') { | ||
exports.command | ||
.output((0, fluent_ffmpeg_multistream_ts_1.StreamOutput)(videoOutput).url, { end: false }) | ||
if (streamOpts.video_codec === 'VP8') { | ||
command | ||
.output(StreamOutput(videoOutput).url, { end: false }) | ||
.noAudio() | ||
.size(`${index_1.streamOpts.width}x${index_1.streamOpts.height}`) | ||
.fpsOutput(index_1.streamOpts.fps || 30) | ||
.videoBitrate(`${index_1.streamOpts.bitrateKbps}k`) | ||
.size(`${streamOpts.width}x${streamOpts.height}`) | ||
.fpsOutput(streamOpts.fps || 30) | ||
.videoBitrate(`${streamOpts.bitrateKbps}k`) | ||
.format('ivf') | ||
@@ -62,8 +57,8 @@ .outputOption('-deadline', 'realtime'); | ||
else { | ||
exports.command | ||
.output((0, fluent_ffmpeg_multistream_ts_1.StreamOutput)(videoOutput).url, { end: false }) | ||
command | ||
.output(StreamOutput(videoOutput).url, { end: false }) | ||
.noAudio() | ||
.size(`${index_1.streamOpts.width}x${index_1.streamOpts.height}`) | ||
.fpsOutput(index_1.streamOpts.fps || 30) | ||
.videoBitrate(`${index_1.streamOpts.bitrateKbps}k`) | ||
.size(`${streamOpts.width}x${streamOpts.height}`) | ||
.fpsOutput(streamOpts.fps || 30) | ||
.videoBitrate(`${streamOpts.bitrateKbps}k`) | ||
.format('h264') | ||
@@ -75,4 +70,4 @@ .outputOptions([ | ||
'-profile:v baseline', | ||
`-g ${index_1.streamOpts.fps}`, | ||
`-x264-params keyint=${index_1.streamOpts.fps}:min-keyint=${index_1.streamOpts.fps}`, | ||
`-g ${streamOpts.fps}`, | ||
`-x264-params keyint=${streamOpts.fps}:min-keyint=${streamOpts.fps}`, | ||
'-bsf:v h264_metadata=aud=insert', | ||
@@ -83,7 +78,7 @@ ]); | ||
if (includeAudio) { | ||
const audioStream = new audio_stream_1.AudioStream(mediaUdp); | ||
const audioStream = new AudioStream(mediaUdp); | ||
// make opus stream | ||
const opus = new prism_media_1.default.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 }); | ||
exports.command | ||
.output((0, fluent_ffmpeg_multistream_ts_1.StreamOutput)(opus).url, { end: false }) | ||
const opus = new prism.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 }); | ||
command | ||
.output(StreamOutput(opus).url, { end: false }) | ||
.noVideo() | ||
@@ -96,10 +91,10 @@ .audioChannels(2) | ||
} | ||
if (index_1.streamOpts.hardware_acceleration) | ||
exports.command.inputOption('-hwaccel', 'auto'); | ||
if (streamOpts.hardware_acceleration) | ||
command.inputOption('-hwaccel', 'auto'); | ||
if (isHttpUrl) { | ||
exports.command.inputOption('-headers', Object.keys(headers) | ||
command.inputOption('-headers', Object.keys(headers) | ||
.map((key) => key + ': ' + headers[key]) | ||
.join('\r\n')); | ||
if (!isHls) { | ||
exports.command.inputOptions([ | ||
command.inputOptions([ | ||
'-reconnect 1', | ||
@@ -112,3 +107,3 @@ '-reconnect_at_eof 1', | ||
} | ||
exports.command.run(); | ||
command.run(); | ||
} | ||
@@ -118,3 +113,3 @@ catch (e) { | ||
//videoStream.end(); | ||
exports.command = undefined; | ||
command = undefined; | ||
reject('cannot play video ' + e.message); | ||
@@ -124,6 +119,5 @@ } | ||
} | ||
exports.streamLivestreamVideo = streamLivestreamVideo; | ||
function getInputMetadata(input) { | ||
export function getInputMetadata(input) { | ||
return new Promise((resolve, reject) => { | ||
const instance = (0, fluent_ffmpeg_1.default)(input).on('error', (err, _stdout, _stderr) => reject(err)); | ||
const instance = ffmpeg(input).on('error', (err, _stdout, _stderr) => reject(err)); | ||
instance.ffprobe((err, metadata) => { | ||
@@ -138,10 +132,7 @@ if (err) | ||
} | ||
exports.getInputMetadata = getInputMetadata; | ||
function inputHasAudio(metadata) { | ||
export function inputHasAudio(metadata) { | ||
return metadata.streams.some((value) => value.codec_type === 'audio'); | ||
} | ||
exports.inputHasAudio = inputHasAudio; | ||
function inputHasVideo(metadata) { | ||
export function inputHasVideo(metadata) { | ||
return metadata.streams.some((value) => value.codec_type === 'video'); | ||
} | ||
exports.inputHasVideo = inputHasVideo; |
@@ -1,5 +0,5 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
/// <reference types="node" resolution-mode="require"/> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { Writable } from 'node:stream'; | ||
import { MediaUdp } from '#src/client/voice/index'; | ||
import { MediaUdp } from '#src/client/index'; | ||
export declare class VideoStream extends Writable { | ||
@@ -6,0 +6,0 @@ udp: MediaUdp; |
@@ -1,6 +0,3 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.VideoStream = void 0; | ||
const node_stream_1 = require("node:stream"); | ||
class VideoStream extends node_stream_1.Writable { | ||
import { Writable } from 'node:stream'; | ||
export class VideoStream extends Writable { | ||
udp; | ||
@@ -37,2 +34,1 @@ count; | ||
} | ||
exports.VideoStream = VideoStream; |
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.normalizeVideoCodec = void 0; | ||
function normalizeVideoCodec(codec) { | ||
export function normalizeVideoCodec(codec) { | ||
if (/H\.?264|AVC/i.test(codec)) | ||
@@ -15,2 +12,1 @@ return 'H264'; | ||
} | ||
exports.normalizeVideoCodec = normalizeVideoCodec; |
{ | ||
"name": "@gabrielmaialva33/discord-video-stream", | ||
"version": "0.1.1", | ||
"version": "0.1.2", | ||
"description": "Experiment for making video streaming work for discord self bots", | ||
@@ -34,4 +34,5 @@ "keywords": [ | ||
}, | ||
"./src": "./src", | ||
"./dist": "./dist", | ||
"./src": "./src" | ||
"./src/*": "./src/*.js" | ||
}, | ||
@@ -38,0 +39,0 @@ "engines": { |
import { BaseMediaPacketizer, MAX_INT16BIT, streamOpts } from '#src/client/index' | ||
import { MediaUdp } from '#src/client/voice/index' | ||
import { MediaUdp } from '#src/client/index' | ||
@@ -4,0 +4,0 @@ /** |
import { Writable } from 'node:stream' | ||
import { MediaUdp } from '#src/client/voice/index' | ||
import { MediaUdp } from '#src/client/index' | ||
@@ -5,0 +5,0 @@ class AudioStream extends Writable { |
@@ -7,3 +7,3 @@ import { Readable, Transform } from 'node:stream' | ||
import { MediaUdp } from '#src/client/voice/index' | ||
import { MediaUdp } from '#src/client/index' | ||
import { VideoStream } from '#src/media/video_stream' | ||
@@ -10,0 +10,0 @@ import { streamOpts } from '#src/client/index' |
import { Writable } from 'node:stream' | ||
import { MediaUdp } from '#src/client/voice/index' | ||
import { MediaUdp } from '#src/client/index' | ||
@@ -5,0 +5,0 @@ export class VideoStream extends Writable { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
154495
4126