-
Notifications
You must be signed in to change notification settings - Fork 32
/
app.js
executable file
·99 lines (86 loc) · 2.6 KB
/
app.js
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
const { Observable, fromEvent, partition, combineLatest, zip } = rxjs;
const { map, flatMap, take, skip } = rxjs.operators;
const bufferStream = filename =>
new Observable(async subscriber => {
const ffmpeg = FFmpeg.createFFmpeg({
corePath: "thirdparty/ffmpeg-core.js",
log: false
});
const fileExists = file => ffmpeg.FS("readdir", "/").includes(file);
const readFile = file => ffmpeg.FS("readFile", file);
await ffmpeg.load();
const sourceBuffer = await fetch(filename).then(r => r.arrayBuffer());
ffmpeg.FS(
"writeFile",
"input.mp4",
new Uint8Array(sourceBuffer, 0, sourceBuffer.byteLength)
);
let index = 0;
ffmpeg
.run(
"-i",
"input.mp4",
"-g",
"1",
// Encode for MediaStream
"-segment_format_options",
"movflags=frag_keyframe+empty_moov+default_base_moof",
// encode 5 second segments
"-segment_time",
"5",
// write to files by index
"-f",
"segment",
"%d.mp4"
)
.then(() => {
// send out the remaining files
while (fileExists(`${index}.mp4`)) {
subscriber.next(readFile(`${index}.mp4`));
index++;
}
subscriber.complete();
});
setInterval(() => {
// periodically check for files that have been written
if (fileExists(`${index + 1}.mp4`)) {
subscriber.next(readFile(`${index}.mp4`));
index++;
}
}, 200);
});
const mediaSource = new MediaSource();
videoPlayer.src = URL.createObjectURL(mediaSource);
videoPlayer.play();
const mediaSourceOpen = fromEvent(mediaSource, "sourceopen");
const bufferStreamReady = combineLatest(
mediaSourceOpen,
bufferStream("tests/4club-JTV-i63.mp4")
).pipe(map(([, a]) => a));
const sourceBufferUpdateEnd = bufferStreamReady.pipe(
take(1),
map(buffer => {
// create a buffer using the correct mime type
const mime = `video/mp4; codecs="${muxjs.mp4.probe
.tracks(buffer)
.map(t => t.codec)
.join(",")}"`;
const sourceBuf = mediaSource.addSourceBuffer(mime);
// append the buffer
mediaSource.duration = 5;
sourceBuf.timestampOffset = 0;
sourceBuf.appendBuffer(buffer);
// create a new event stream
return fromEvent(sourceBuf, "updateend").pipe(map(() => sourceBuf));
}),
flatMap(value => value)
);
zip(sourceBufferUpdateEnd, bufferStreamReady.pipe(skip(1)))
.pipe(
map(([sourceBuf, buffer]) => {
mediaSource.duration += 5;
sourceBuf.timestampOffset += 5;
sourceBuf.appendBuffer(buffer.buffer);
})
)
.subscribe();