feat(VoiceReceiver): Proof of concept - Video recording
This commit is contained in:
@@ -5,6 +5,8 @@ const { createSocket } = require('dgram');
|
||||
const { EventEmitter } = require('events');
|
||||
const { Buffer } = require('node:buffer');
|
||||
const { Writable } = require('stream');
|
||||
const find = require('find-process');
|
||||
const kill = require('tree-kill');
|
||||
const Util = require('../../../util/Util');
|
||||
const { StreamOutput } = require('../util/Socket');
|
||||
|
||||
@@ -46,11 +48,7 @@ class FFmpegHandler extends EventEmitter {
|
||||
*/
|
||||
this.ready = false;
|
||||
|
||||
/**
|
||||
* The FFmpeg process
|
||||
* @type {ChildProcessWithoutNullStreams}
|
||||
*/
|
||||
this.stream = spawn('ffmpeg', [
|
||||
const stream = spawn('ffmpeg', [
|
||||
'-reorder_queue_size',
|
||||
'50',
|
||||
'-err_detect',
|
||||
@@ -73,9 +71,15 @@ class FFmpegHandler extends EventEmitter {
|
||||
'500000',
|
||||
'-y',
|
||||
'-f', // Specify the format
|
||||
'matroska', // MKV format
|
||||
'mpegts', // MKV format
|
||||
isStream ? this.outputStream.url : output,
|
||||
]);
|
||||
|
||||
/**
|
||||
* The FFmpeg process
|
||||
* @type {ChildProcessWithoutNullStreams}
|
||||
*/
|
||||
this.stream = stream;
|
||||
this.stream.stdin.write(sdpData);
|
||||
this.stream.stdin.end();
|
||||
this.stream.stderr.once('data', data => {
|
||||
@@ -101,6 +105,17 @@ class FFmpegHandler extends EventEmitter {
|
||||
const message = Buffer.from(payload);
|
||||
this.socket.send(message, 0, message.length, this.portUdp, '127.0.0.1', callback);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
const ffmpegPid = this.stream.pid; // But it is ppid ;-;
|
||||
const args = this.stream.spawnargs.slice(1).join(' '); // Skip ffmpeg
|
||||
find('name', 'ffmpeg', true).then(list => {
|
||||
let process = list.find(o => o.pid === ffmpegPid || o.ppid === ffmpegPid || o.cmd.includes(args));
|
||||
if (process) {
|
||||
kill(process.pid);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FFmpegHandler;
|
||||
|
||||
@@ -59,6 +59,7 @@ class VoiceReceiver extends EventEmitter {
|
||||
* @typedef {Object} ReceiveVideoStreamOptions
|
||||
* @property {number} [portUdp] The UDP port to use for the video stream (local stream).
|
||||
* @property {string} [codec='H264'] The codec to use for encoding the video. Default is 'H264'.
|
||||
* <info>H265 supported, but not implemented</info>
|
||||
* @property {any} [output] Additional output options, as required.
|
||||
*/
|
||||
|
||||
@@ -70,9 +71,10 @@ class VoiceReceiver extends EventEmitter {
|
||||
* @param {ReceiveVideoStreamOptions} options Options.
|
||||
* @returns {FFmpegHandler} The video stream for the specified user.
|
||||
*/
|
||||
createVideoStream(user, { portUdp, codec = 'H264', output } = {}) {
|
||||
createVideoStream(user, { portUdp, codec, output } = {}) {
|
||||
user = this.connection.client.users.resolve(user);
|
||||
if (!user) throw new Error('VOICE_USER_MISSING');
|
||||
codec = 'H264';
|
||||
const stream = this.packets.makeVideoStream(user.id, portUdp, codec, output);
|
||||
return stream;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ const payloadTypes = [
|
||||
priority: 5000,
|
||||
payload_type: 109,
|
||||
rtx_payload_type: 110,
|
||||
encode: true,
|
||||
encode: false,
|
||||
decode: false,
|
||||
},
|
||||
];
|
||||
@@ -951,7 +951,6 @@ class Util extends null {
|
||||
payloadType = payload.payload_type;
|
||||
} else {
|
||||
const payloadType = packet[1] > 120 ? packet[1] & 0x80 : packet[1];
|
||||
console.log('payloadType', payloadType, packet, portUdp);
|
||||
payload = payloadTypes.find(p => p.payload_type === payloadType);
|
||||
}
|
||||
let sdpData = `o=- 0 0 IN IP4 127.0.0.1
|
||||
|
||||
Reference in New Issue
Block a user