Adding more options
This commit is contained in:
parent
d59a58f63d
commit
9b92a43c2f
172
src/index.ts
172
src/index.ts
@ -1,4 +1,4 @@
|
|||||||
import { ChildProcess, spawn } from "child_process"
|
import { ChildProcess, spawn } from "child_process";
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { Writable } from "stream";
|
import { Writable } from "stream";
|
||||||
import { IOptions } from "./options";
|
import { IOptions } from "./options";
|
||||||
@ -7,88 +7,114 @@ const ef1 = "ff";
|
|||||||
const ef2 = "d9";
|
const ef2 = "d9";
|
||||||
|
|
||||||
export class Rtsp extends EventEmitter {
|
export class Rtsp extends EventEmitter {
|
||||||
private _connecteionString: string;
|
private _connecteionString: string;
|
||||||
private _childProcess: ChildProcess | undefined;
|
private _childProcess: ChildProcess | undefined;
|
||||||
private _started: boolean;
|
private _started: boolean;
|
||||||
private _buffer: Buffer;
|
private _buffer: Buffer;
|
||||||
private _options: IOptions;
|
private _options: IOptions;
|
||||||
|
private _paused: boolean;
|
||||||
|
|
||||||
constructor(connectionString: string, options: IOptions) {
|
constructor(connectionString: string, options: IOptions) {
|
||||||
super();
|
super();
|
||||||
this._started = false;
|
this._started = false;
|
||||||
this._connecteionString = connectionString;
|
this._connecteionString = connectionString;
|
||||||
this._childProcess = undefined;
|
this._childProcess = undefined;
|
||||||
this._buffer = Buffer.from('');
|
this._buffer = Buffer.from("");
|
||||||
this._options = options;
|
this._options = options;
|
||||||
|
this._paused = false;
|
||||||
|
|
||||||
|
this.onData = this.onData.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isStarted(): boolean {
|
||||||
|
return this._started;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isPaused(): boolean {
|
||||||
|
return this._paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
public start(): void {
|
||||||
|
const argStrings = [
|
||||||
|
// `-rtsp_transport tcp`,
|
||||||
|
`-i ${this._connecteionString}`,
|
||||||
|
`-r ${this._options.rate ?? 10}`,
|
||||||
|
this._options.image
|
||||||
|
? `-f image2`
|
||||||
|
: `-codec:v ${this._options.codec ?? "libx264"}`,
|
||||||
|
`-update 1 -`,
|
||||||
|
];
|
||||||
|
const args = argStrings.join(" ");
|
||||||
|
this._childProcess = spawn("ffmpeg", args.split(/\s+/));
|
||||||
|
|
||||||
|
if (!this._childProcess) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get isStarted(): boolean {
|
this._childProcess.stdout?.on("data", this.onData);
|
||||||
return this._started;
|
this._childProcess.on("exit", this.onExit);
|
||||||
|
this._childProcess.on("error", this.onError);
|
||||||
|
|
||||||
|
if (this._childProcess.stderr) {
|
||||||
|
this._childProcess.stderr.on("data", this.onStdErrorData);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public start(): void {
|
public close(): void {
|
||||||
const argStrings = [
|
this._childProcess && this._childProcess.kill("SIGKILL");
|
||||||
`-i ${this._connecteionString}`,
|
this.emit("closed");
|
||||||
`-r ${this._options.rate ?? 10}`,
|
}
|
||||||
`-f image2`,
|
|
||||||
`-codec:v ${this._options.codec ?? 'libx264'}`,
|
|
||||||
`-update 1 -`
|
|
||||||
];
|
|
||||||
const args = argStrings.join(" ");
|
|
||||||
this._childProcess = spawn("ffmpeg", args.split(/\s+/));
|
|
||||||
|
|
||||||
if(!this._childProcess){
|
public pause(): void {
|
||||||
return;
|
this._paused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._childProcess.stdout?.on('data', this.onData)
|
|
||||||
this._childProcess.on('exit', this.onExit);
|
|
||||||
this._childProcess.on('error', this.onError);
|
|
||||||
|
|
||||||
if (this._childProcess.stderr) {
|
public resume(): void {
|
||||||
this._childProcess.stderr.on('data', this.onStdErrorData);
|
this._paused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getStdin(): Writable | null {
|
||||||
|
return this._childProcess ? this._childProcess.stdin : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private onError = (err: Error): void => {
|
||||||
|
this.emit("error", new Error("Failed to start stream: " + err.message));
|
||||||
|
};
|
||||||
|
|
||||||
|
private onStdErrorData = (data: any): void => {
|
||||||
|
if (!this._started) {
|
||||||
|
this._started = true;
|
||||||
}
|
}
|
||||||
|
let msg = "";
|
||||||
|
data
|
||||||
|
.toString()
|
||||||
|
.split(/\n/)
|
||||||
|
.forEach((line: string) => {
|
||||||
|
msg += `${line}\n`;
|
||||||
|
});
|
||||||
|
|
||||||
public close(): void {
|
this.emit("error", msg);
|
||||||
this._childProcess && this._childProcess.kill('SIGKILL');
|
};
|
||||||
this.emit('closed');
|
|
||||||
}
|
|
||||||
|
|
||||||
public getStdin(): Writable | null {
|
private onExit = (code: number, signal: NodeJS.Signals): void => {
|
||||||
return this._childProcess ? this._childProcess.stdin : null;
|
const message =
|
||||||
|
"FFmpeg exited with code: " + code + " and signal: " + signal;
|
||||||
|
this.emit("closed", message);
|
||||||
|
};
|
||||||
|
|
||||||
|
private onData(data: Buffer): void {
|
||||||
|
if (!this._paused && data.length > 1) {
|
||||||
|
this._buffer = this._buffer
|
||||||
|
? Buffer.concat([this._buffer, data])
|
||||||
|
: (this._buffer = Buffer.from(data));
|
||||||
|
//End of image
|
||||||
|
if (
|
||||||
|
data[data.length - 2].toString(16) == ef1 &&
|
||||||
|
data[data.length - 1].toString(16) == ef2
|
||||||
|
) {
|
||||||
|
this.emit("data", this._buffer);
|
||||||
|
this._buffer = Buffer.from("");
|
||||||
}
|
}
|
||||||
|
|
||||||
private onError = (err: Error): void => {
|
|
||||||
this.emit('error', new Error('Failed to start stream: ' + err.message));
|
|
||||||
}
|
|
||||||
|
|
||||||
private onStdErrorData = (data: any): void => {
|
|
||||||
if (!this._started) {
|
|
||||||
this._started = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
let msg = "";
|
|
||||||
data.toString().split(/\n/).forEach((line: string) => {
|
|
||||||
msg += `line\n`;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.emit("error", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private onExit = (code: number, signal: NodeJS.Signals): void => {
|
|
||||||
const message = 'FFmpeg exited with code: ' + code + ' and signal: ' + signal;
|
|
||||||
this.emit('closed', message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private onData = (data: Buffer): void => {
|
|
||||||
if (data.length > 1) {
|
|
||||||
this._buffer = this._buffer ? Buffer.concat([this._buffer, data]) : this._buffer = Buffer.from(data);
|
|
||||||
//End of image
|
|
||||||
if(data[data.length - 2].toString(16) == ef1 && data[data.length -1].toString(16) == ef2){
|
|
||||||
this.emit('data', this._buffer)
|
|
||||||
this._buffer = Buffer.from('');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
export interface IOptions {
|
export interface IOptions {
|
||||||
rate?: number,
|
rate?: number;
|
||||||
quality?: number,
|
quality?: number;
|
||||||
resolution?: string,
|
resolution?: string;
|
||||||
codec?: string,
|
codec?: string;
|
||||||
}
|
image?: boolean;
|
||||||
|
}
|
||||||
|
8
workspace.code-workspace
Normal file
8
workspace.code-workspace
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user