Skip to content

Commit fb237da

Browse files
committed
test: add tests and improve existing tests
1 parent 0c06ad2 commit fb237da

File tree

7 files changed

+116
-31
lines changed

7 files changed

+116
-31
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ tsconfig.*.tsbuildinfo
3131
.env.development.local
3232
.env.test.local
3333
.env.production.local
34+
.temp
3435
npm-debug.log*
3536
yarn-debug.log*
3637
yarn-error.log*

src/FFmpeggy.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export interface FFmpeggyOptions {
2121
hideBanner?: boolean;
2222
}
2323

24-
type FFmpeggyProgressEvent = FFmpeggyProgress & {
24+
export type FFmpeggyProgressEvent = FFmpeggyProgress & {
2525
duration?: number;
2626
percent?: number;
2727
};
@@ -139,9 +139,15 @@ export class FFmpeggy extends (EventEmitter as new () => TypedEmitter<FFmpegEven
139139
const ffmpegInput = input instanceof ReadStream ? "pipe:" : input;
140140
const ffmpegOutput = output instanceof WriteStream ? "pipe:" : output;
141141

142+
if (this.hideBanner) {
143+
globalOptions.push("-hide_banner");
144+
}
145+
146+
if (this.overwriteExisting) {
147+
globalOptions.push("-y");
148+
}
149+
142150
const args = [
143-
...(this.hideBanner ? ["-hide_banner"] : []),
144-
...(this.overwriteExisting ? ["-y"] : []),
145151
...globalOptions.join(" ").split(" "),
146152
...inputOptions.join(" ").split(" "),
147153
...["-i", ffmpegInput],
@@ -200,7 +206,7 @@ export class FFmpeggy extends (EventEmitter as new () => TypedEmitter<FFmpegEven
200206
this.error = e;
201207
debug("error: %o", e);
202208
this.emit("error", e);
203-
this.emit("exit");
209+
this.emit("exit", 1, e);
204210
this.running = false;
205211
}
206212

src/__tests__/FFmpeggy.spec.ts

Lines changed: 105 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import fs, { createWriteStream, createReadStream } from "fs";
22
import path from "path";
3-
import { path as ffmpegBin } from "@ffmpeg-installer/ffmpeg";
4-
import { path as ffprobeBin } from "@ffprobe-installer/ffprobe";
3+
import ffmpegBin from "ffmpeg-static";
4+
import { path as ffprobeBin } from "ffprobe-static";
55
import { file as tmpFile } from "tempy";
66
import { waitFile } from "wait-file";
7-
import { FFmpeggy } from "../FFmpeggy";
7+
import { FFmpeggy, FFmpeggyProgressEvent } from "../FFmpeggy";
88

9-
// NOTE: "fs/promises" is not available in node 12
10-
const { unlink, stat } = fs.promises;
9+
// NOTE: "fs/promises" is not available in node 12 =(
10+
const { mkdir, rmdir, unlink, stat } = fs.promises;
1111

1212
FFmpeggy.DefaultConfig = {
1313
...FFmpeggy.DefaultConfig,
@@ -17,9 +17,9 @@ FFmpeggy.DefaultConfig = {
1717
};
1818

1919
describe("FFmpeggy", () => {
20-
const sampleMp4 = path.join(__dirname, "samples/sample1.mp4");
21-
const sampleMkv = path.join(__dirname, "samples/sample1.mkv");
22-
const sampleMp3 = path.join(__dirname, "samples/sample1.mp3");
20+
const sampleMkv = path.join(__dirname, "samples/bunny1.mkv");
21+
const sampleMp4 = path.join(__dirname, "samples/bunny2.mp4");
22+
const sampleMp3 = path.join(__dirname, "samples/audio.mp3");
2323
const tempFiles: string[] = [];
2424

2525
// bump jest timeout since file ops can take some time
@@ -31,18 +31,33 @@ describe("FFmpeggy", () => {
3131
return file;
3232
}
3333

34+
beforeAll(async () => {
35+
try {
36+
await mkdir(path.join(__dirname, "samples/.temp/"));
37+
} catch {
38+
// Ignore
39+
}
40+
});
41+
3442
afterAll(async () => {
3543
// Clean up temp files
36-
await waitFile({ resources: tempFiles });
37-
await Promise.allSettled(tempFiles.map(unlink));
44+
if (tempFiles.length > 0) {
45+
await waitFile({ resources: tempFiles });
46+
await Promise.allSettled(tempFiles.map(unlink));
47+
}
48+
try {
49+
await rmdir(path.join(__dirname, "samples/.temp/"), { recursive: true });
50+
} catch {
51+
// Ignore
52+
}
3853
});
3954

4055
it("should initialize", () => {
4156
const ffmpeggy = new FFmpeggy();
4257
expect(ffmpeggy).toBeInstanceOf(FFmpeggy);
4358
});
4459

45-
it("should copy sample.mp4 to temp file", (done) => {
60+
it("should copy bunny2.mp4 to temp file", (done) => {
4661
const ffmpeggy = new FFmpeggy();
4762
const tempFile = getTempFile("mp4");
4863
ffmpeggy
@@ -64,7 +79,7 @@ describe("FFmpeggy", () => {
6479
});
6580
});
6681

67-
it("should stream sample1.mkv to temp file", async () => {
82+
it("should stream bunny1.mkv to temp file", async () => {
6883
const tempFile = getTempFile("mkv");
6984
const ffmpeggy = new FFmpeggy({
7085
autorun: true,
@@ -79,7 +94,7 @@ describe("FFmpeggy", () => {
7994
expect(pipedStats.size).toBeGreaterThan(0);
8095
});
8196

82-
it("should stream sample1.mp3 to temp file", async () => {
97+
it("should stream audio.mp3 to temp file", async () => {
8398
const tempFile = getTempFile("mp3");
8499
const ffmpeggy = new FFmpeggy({
85100
autorun: true,
@@ -94,7 +109,7 @@ describe("FFmpeggy", () => {
94109
expect(pipedStats.size).toBeGreaterThan(0);
95110
});
96111

97-
it("should receive progress event", (done) => {
112+
it.only("should receive progress event", (done) => {
98113
expect.assertions(9);
99114
const tempFile = getTempFile("mp4");
100115
const ffmpeggy = new FFmpeggy();
@@ -104,21 +119,84 @@ describe("FFmpeggy", () => {
104119
.setOutput(tempFile)
105120
.run();
106121

107-
ffmpeggy.on("progress", async (e) => {
108-
expect(e.frame).toBeGreaterThan(0);
109-
expect(e.fps).toBeDefined();
110-
expect(e.q).toBeDefined();
111-
expect(e.size).toBe(1055744);
112-
expect(e.time).toBeGreaterThan(0);
113-
expect(e.bitrate).toBeGreaterThan(0);
114-
expect(e.speed).toBeGreaterThan(0);
115-
expect(e.duration).toBeDefined();
116-
expect(e.percent).toBeGreaterThan(0);
122+
let progress: FFmpeggyProgressEvent;
123+
ffmpeggy.on("progress", async (p) => {
124+
progress = p;
117125
});
118126

119-
ffmpeggy.on("exit", async () => {
120-
done();
127+
ffmpeggy.on("exit", async (code, error) => {
128+
expect(progress.frame).toBeGreaterThan(0);
129+
expect(progress.fps).toBeDefined();
130+
expect(progress.q).toBeDefined();
131+
expect(progress.size).toBe(1055744);
132+
expect(progress.time).toBeGreaterThan(0);
133+
expect(progress.bitrate).toBeGreaterThan(0);
134+
expect(progress.speed).toBeGreaterThan(0);
135+
expect(progress.duration).toBeDefined();
136+
expect(progress.percent).toBeGreaterThan(0);
137+
138+
if (code === 1 || error) {
139+
done.fail(error);
140+
} else {
141+
done();
142+
}
143+
});
144+
});
145+
146+
it("should emit writing and done events for segments", (done) => {
147+
expect.assertions(10);
148+
const ffmpeggy = new FFmpeggy({
149+
input: sampleMkv,
150+
output: path.join(__dirname, "samples/.temp/temp-%d.mpegts"),
151+
outputOptions: [
152+
"-t 5",
153+
"-map 0",
154+
"-c:v libx264",
155+
"-c:a aac",
156+
"-r 25",
157+
"-force_key_frames expr:gte(t,n_forced*1)",
158+
"-f ssegment",
159+
"-forced-idr 1",
160+
"-flags +cgop",
161+
"-copyts",
162+
"-vsync -1",
163+
"-avoid_negative_ts disabled",
164+
"-individual_header_trailer 0",
165+
"-start_at_zero",
166+
"-segment_list_type m3u8",
167+
`-segment_list ${path.join(__dirname, "samples/.temp/playlist.m3u8")}`,
168+
"-segment_time 1",
169+
"-segment_format mpegts",
170+
],
121171
});
172+
173+
let fileIdx = 0;
174+
ffmpeggy.on("writing", (file) => {
175+
if (file.includes("temp-")) {
176+
expect(file).toBe(
177+
path.join(__dirname, "samples/.temp/", `temp-${fileIdx}.mpegts`)
178+
);
179+
}
180+
});
181+
182+
ffmpeggy.on("done", (file) => {
183+
if (file?.includes("temp-")) {
184+
expect(file).toBe(
185+
path.join(__dirname, "samples/.temp/", `temp-${fileIdx}.mpegts`)
186+
);
187+
fileIdx++;
188+
}
189+
});
190+
191+
ffmpeggy.on("exit", (code, error) => {
192+
if (code === 1 || error) {
193+
done.fail(error);
194+
} else {
195+
done();
196+
}
197+
});
198+
199+
ffmpeggy.run();
122200
});
123201

124202
describe("toStream()", () => {
@@ -141,7 +219,7 @@ describe("FFmpeggy", () => {
141219
});
142220

143221
describe("probe", () => {
144-
it("should probe sample.mp4", async () => {
222+
it("should probe bunny2.mp4", async () => {
145223
expect.assertions(5);
146224
const result = await FFmpeggy.probe(sampleMp4);
147225
expect(result.format).toBeDefined();

src/__tests__/samples/bunny1.mkv

22.3 MB
Binary file not shown.

src/__tests__/samples/sample1.mkv

-1.26 MB
Binary file not shown.

0 commit comments

Comments
 (0)