mirror of
https://github.com/koush/scrypted.git
synced 2026-06-21 00:50:30 +01:00
ffmpeg ordering fixups
This commit is contained in:
114
common/src/ffmpeg-rebroadcast.ts
Normal file
114
common/src/ffmpeg-rebroadcast.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import { createServer, Socket, Server } from 'net';
|
||||
import child_process from 'child_process';
|
||||
import { ChildProcess } from 'child_process';
|
||||
import { FFMpegInput } from '@scrypted/sdk/types';
|
||||
import { listenZeroCluster } from './listen-cluster';
|
||||
import { readLength } from './read-length';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
export interface MP4Atom {
|
||||
header: Buffer;
|
||||
length: number;
|
||||
type: string;
|
||||
data: Buffer;
|
||||
}
|
||||
|
||||
export interface FFMpegRebroadcastSession {
|
||||
server: Server;
|
||||
cp: ChildProcess;
|
||||
ffmpegInput: FFMpegInput;
|
||||
}
|
||||
|
||||
export interface FFMpegRebroadcastOptions {
|
||||
vcodec: string;
|
||||
acodec: string;
|
||||
}
|
||||
|
||||
export async function startRebroadcastSession(ffmpegInput: FFMpegInput, options: FFMpegRebroadcastOptions): Promise<FFMpegRebroadcastSession> {
|
||||
return new Promise(async (resolve) => {
|
||||
let clients = 0;
|
||||
let timeout: any;
|
||||
const startTimeout = () => {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => {
|
||||
cp?.kill();
|
||||
server?.close();
|
||||
rebroadcast?.close();
|
||||
}, 30000);
|
||||
}
|
||||
startTimeout();
|
||||
|
||||
const events = new EventEmitter();
|
||||
|
||||
const rebroadcast = createServer(socket => {
|
||||
console.log('rebroadcast client');
|
||||
clients++;
|
||||
|
||||
clearTimeout(timeout)
|
||||
|
||||
const data = (data: Buffer) => {
|
||||
socket.write(data);
|
||||
};
|
||||
const cleanup = () => {
|
||||
socket.removeAllListeners();
|
||||
events.removeListener('data', data);
|
||||
clients--;
|
||||
if (clients === 0) {
|
||||
startTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
events.on('data', data);
|
||||
|
||||
socket.on('end', cleanup);
|
||||
socket.on('close', cleanup);
|
||||
socket.on('error', cleanup);
|
||||
});
|
||||
|
||||
const rebroadcastPort = await listenZeroCluster(rebroadcast);
|
||||
|
||||
const server = createServer(socket => {
|
||||
server.close();
|
||||
|
||||
(async() => {
|
||||
while (true) {
|
||||
const data = await readLength(socket, 188);
|
||||
events.emit('data', data);
|
||||
}
|
||||
})();
|
||||
|
||||
resolve({
|
||||
server: rebroadcast,
|
||||
cp,
|
||||
ffmpegInput: {
|
||||
inputArguments: [
|
||||
'-f',
|
||||
'mpegts',
|
||||
'-i',
|
||||
`tcp://127.0.0.1:${rebroadcastPort}`
|
||||
]
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const serverPort = await listenZeroCluster(server);
|
||||
|
||||
const args = ffmpegInput.inputArguments.slice();
|
||||
|
||||
args.push(
|
||||
'-f', 'mpegts',
|
||||
'-vcodec', options.vcodec,
|
||||
...(options.acodec ? ['-acodec', options.acodec] : ['-an']),
|
||||
`tcp://127.0.0.1:${serverPort}`
|
||||
);
|
||||
|
||||
console.log(args);
|
||||
|
||||
const cp = child_process.spawn('ffmpeg', args, {
|
||||
// stdio: 'ignore',
|
||||
});
|
||||
cp.stdout.on('data', data => console.log(data.toString()));
|
||||
cp.stderr.on('data', data => console.error(data.toString()));
|
||||
|
||||
});
|
||||
}
|
||||
4
plugins/amcrest/package-lock.json
generated
4
plugins/amcrest/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/amcrest",
|
||||
"version": "0.0.18",
|
||||
"version": "0.0.19",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/amcrest",
|
||||
"version": "0.0.18",
|
||||
"version": "0.0.19",
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"@mhoc/axios-digest-auth": "^0.7.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/amcrest",
|
||||
"version": "0.0.18",
|
||||
"version": "0.0.19",
|
||||
"description": "Amcrest Plugin for Scrypted",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache",
|
||||
|
||||
@@ -59,14 +59,14 @@ class AmcrestCamera extends ScryptedDeviceBase implements VideoCamera, Camera, S
|
||||
|
||||
return mediaManager.createFFmpegMediaObject({
|
||||
inputArguments: [
|
||||
"-i",
|
||||
url,
|
||||
'-analyzeduration', '15000000',
|
||||
'-probesize', '100000000',
|
||||
"-reorder_queue_size",
|
||||
"1024",
|
||||
"-max_delay",
|
||||
"20000000",
|
||||
"-i",
|
||||
url,
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
4
plugins/core/package-lock.json
generated
4
plugins/core/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/core",
|
||||
"version": "0.0.61",
|
||||
"version": "0.0.62",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/core",
|
||||
"version": "0.0.61",
|
||||
"version": "0.0.62",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@scrypted/sdk": "file:../../sdk",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/core",
|
||||
"version": "0.0.61",
|
||||
"version": "0.0.62",
|
||||
"description": "Scrypted Core plugin. Provides the UI, websocket, and engine.io APIs.",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -85,10 +85,6 @@ function createVideoCamera(devices: VideoCamera[]): VideoCamera {
|
||||
filter.push(`[${i}:v] setpts=PTS-STARTPTS, scale=${w}x${h} [pos${i}];`)
|
||||
}
|
||||
|
||||
filteredInput.inputArguments.push(
|
||||
'-f', 'lavfi', '-i', 'anullsrc',
|
||||
)
|
||||
|
||||
let prev = 'base';
|
||||
let curx = 0;
|
||||
let cury = 0;
|
||||
@@ -109,9 +105,10 @@ function createVideoCamera(devices: VideoCamera[]): VideoCamera {
|
||||
filter.join(' '),
|
||||
);
|
||||
|
||||
// return mediaManager.createFFmpegMediaObject(ret);
|
||||
|
||||
const ret = await startRebroadcastSession(filteredInput);
|
||||
const ret = await startRebroadcastSession(filteredInput, {
|
||||
vcodec: 'libx264',
|
||||
acodec: undefined,
|
||||
});
|
||||
return mediaManager.createFFmpegMediaObject(ret.ffmpegInput);
|
||||
}
|
||||
}
|
||||
|
||||
4
plugins/google-device-access/package-lock.json
generated
4
plugins/google-device-access/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/google-device-access",
|
||||
"version": "0.0.10",
|
||||
"version": "0.0.11",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/google-device-access",
|
||||
"version": "0.0.10",
|
||||
"version": "0.0.11",
|
||||
"dependencies": {
|
||||
"@googleapis/smartdevicemanagement": "^0.2.0",
|
||||
"axios": "^0.21.1",
|
||||
|
||||
@@ -36,5 +36,5 @@
|
||||
"@types/node": "^14.17.11",
|
||||
"@types/url-parse": "^1.4.3"
|
||||
},
|
||||
"version": "0.0.10"
|
||||
"version": "0.0.11"
|
||||
}
|
||||
|
||||
@@ -76,14 +76,14 @@ class NestCamera extends ScryptedDeviceBase implements VideoCamera, MotionSensor
|
||||
inputArguments: [
|
||||
"-rtsp_transport",
|
||||
"tcp",
|
||||
"-i",
|
||||
u.toString(),
|
||||
'-analyzeduration', '15000000',
|
||||
'-probesize', '100000000',
|
||||
"-reorder_queue_size",
|
||||
"1024",
|
||||
"-max_delay",
|
||||
"20000000",
|
||||
"-i",
|
||||
u.toString(),
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,10 +24,14 @@ addSupportedType({
|
||||
ret.attributes['colorModel'] = 'rgb';
|
||||
|
||||
if (device.interfaces.includes(ScryptedInterface.ColorSettingTemperature)) {
|
||||
ret.attributes.colorTemperatureRange = {
|
||||
temperatureMinK: await device.getTemperatureMinK(),
|
||||
temperatureMaxK: await device.getTemperatureMaxK(),
|
||||
};
|
||||
try {
|
||||
ret.attributes.colorTemperatureRange = {
|
||||
temperatureMinK: await device.getTemperatureMinK(),
|
||||
temperatureMaxK: await device.getTemperatureMaxK(),
|
||||
};
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
4
plugins/rtsp/package-lock.json
generated
4
plugins/rtsp/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/rtsp",
|
||||
"version": "0.0.16",
|
||||
"version": "0.0.17",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/rtsp",
|
||||
"version": "0.0.16",
|
||||
"version": "0.0.17",
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"axios": "^0.18.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/rtsp",
|
||||
"version": "0.0.16",
|
||||
"version": "0.0.17",
|
||||
"description": "RTSP Cameras and Streams Plugin for Scrypted",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache",
|
||||
|
||||
@@ -19,14 +19,14 @@ class RtspCamera extends ScryptedDeviceBase implements VideoCamera, Settings {
|
||||
|
||||
return mediaManager.createFFmpegMediaObject({
|
||||
inputArguments: [
|
||||
"-i",
|
||||
url.toString(),
|
||||
'-analyzeduration', '15000000',
|
||||
'-probesize', '100000000',
|
||||
"-reorder_queue_size",
|
||||
"1024",
|
||||
"-max_delay",
|
||||
"20000000",
|
||||
"-i",
|
||||
url.toString(),
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
4
plugins/unifi-protect/package-lock.json
generated
4
plugins/unifi-protect/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/unifi-protect",
|
||||
"version": "0.0.23",
|
||||
"version": "0.0.24",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/unifi-protect",
|
||||
"version": "0.0.23",
|
||||
"version": "0.0.24",
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"@types/ws": "^7.4.7",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/unifi-protect",
|
||||
"version": "0.0.23",
|
||||
"version": "0.0.24",
|
||||
"description": "Unifi Protect Plugin for Scrypted",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache",
|
||||
|
||||
Reference in New Issue
Block a user