forked from milanjrodd/srt2rtmp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
100 lines (83 loc) · 2.49 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { $, env } from "bun";
const ENCODING_PRESETS = [
"ultrafast",
"superfast",
"veryfast",
"faster",
"fast",
"medium",
"slow",
"slower",
"veryslow",
] as const;
type EncodingPreset = (typeof ENCODING_PRESETS)[number];
interface IEncoderOptions {
audioSamplingRate: number;
videoBitrate: number;
reconnectDelayInSeconds: number;
inputBufferSizeInKB: number;
bufferSize?: number;
frameRate: number;
preset: EncodingPreset;
bframes: number;
}
async function SendSrtToRtmp(
srtUrl: string,
rtmpUrl: string,
autoInstall = true,
encoderOptions: IEncoderOptions = {
audioSamplingRate: 44100,
videoBitrate: 8000,
inputBufferSizeInKB: 1024,
reconnectDelayInSeconds: 2,
frameRate: 48,
preset: "ultrafast",
bframes: 2,
}
) {
if (!srtUrl) throw new Error("SRT URL is required");
if (!rtmpUrl) throw new Error("RTMP URL is required");
const srtParams = {
recv_buffer_size: encoderOptions.inputBufferSizeInKB * 1024,
snddropdelay: encoderOptions.reconnectDelayInSeconds * 1000 * 1000,
};
const srtUrlWithParams = new URL(srtUrl);
for (const [key, value] of Object.entries(srtParams)) {
srtUrlWithParams.searchParams.append(key, value.toString());
}
const args = {
i: srtUrlWithParams.toString(),
ar: encoderOptions.audioSamplingRate,
cv: "libx264",
x264opts: `nal-hrd=cbr:bframes=${encoderOptions.bframes}:keyint=${
2 * encoderOptions.frameRate
}:no-scenecut`,
preset: encoderOptions.preset,
ca: "aac",
ba: "160k",
bv: `${encoderOptions.videoBitrate}k`,
bufsize: `${encoderOptions.bufferSize ?? encoderOptions.videoBitrate * 2}k`,
filterv: `fps=${encoderOptions.frameRate}`,
f: "flv",
};
const { stdout, stderr, exitCode, } = await $`ffmpeg -re -i ${args.i} -ar ${args.ar} -c:v ${args.cv} -x264opts ${args.x264opts} -preset ${args.preset} -c:a ${args.ca} -b:a ${args.ba} -b:v ${args.bv} -bufsize ${args.bufsize} -filter:v ${args.filterv} -f ${args.f} ${rtmpUrl}`
.nothrow()
.quiet()
if (exitCode !== 0) {
console.log(`Non-zero exit code ${exitCode}`);
}
console.log(stdout.toString());
console.log(stderr.toString());
Bun.sleep(1000);
return SendSrtToRtmp(srtUrl, rtmpUrl);
}
const srtUrl = env.SRT_URL;
const rtmpUrl = env.RTMP_URL;
// Run in loop with 1 second delay
Bun.serve({
fetch(req: Request): Response | Promise<Response> {
return new Response("Hello World!");
},
port: process.env.PORT,
});
new Promise(() => SendSrtToRtmp(srtUrl, rtmpUrl));