-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathmp4.ts
80 lines (68 loc) · 1.97 KB
/
mp4.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
import MP4Box from 'mp4box';
import type { Input, RegisterInputResult } from '../input';
import type { InstanceContext } from '../instance';
import { MAIN_SAMPLE_RATE } from '../AudioMixer';
export class Mp4Input implements Input {
private inputId: string;
private ctx: InstanceContext;
constructor(inputId: string, ctx: InstanceContext) {
this.inputId = inputId;
this.ctx = ctx;
}
public async terminate(): Promise<void> {
await this.ctx.audioMixer.removeInput(this.inputId);
}
}
export async function handleRegisterMp4Input(
ctx: InstanceContext,
inputId: string,
arrayBuffer: ArrayBuffer
): Promise<RegisterInputResult> {
const metadata = await parseMp4(arrayBuffer);
let messagePort;
if (metadata?.sampleRate === MAIN_SAMPLE_RATE) {
messagePort = ctx.audioMixer.addWorkletInput(inputId);
} else if (metadata?.sampleRate) {
messagePort = await ctx.audioMixer.addWorkletInputWithResample(inputId, metadata.sampleRate);
}
return {
input: new Mp4Input(inputId, ctx),
workerMessage: [
{
type: 'registerInput',
inputId,
input: {
type: 'mp4',
arrayBuffer,
audioWorkletMessagePort: messagePort,
},
},
[...(messagePort ? [messagePort] : []), arrayBuffer],
],
};
}
async function parseMp4(buffer: ArrayBuffer): Promise<{ sampleRate?: number }> {
(buffer as any).fileStart = 0;
const file = MP4Box.createFile();
const result = new Promise<{ sampleRate?: number }>((res, rej) => {
file.onReady = info => {
try {
res(parseMp4Info(info));
} catch (err: any) {
rej(err);
}
};
file.onError = (error: string) => {
rej(new Error(error));
};
});
file.appendBuffer(buffer as any);
return result;
}
function parseMp4Info(info: MP4Box.MP4Info): { sampleRate?: number } {
const audioTrack = info.audioTracks[0];
if (!audioTrack) {
return {};
}
return { sampleRate: audioTrack.audio.sample_rate };
}