feat: initial commit - Jhonny Editor
- Adicionado estrutura completa do projeto - Configurado MCP server para Premiere Pro - Adicionado documentação e skills - Configurado Gitignore para o projeto
This commit is contained in:
Executable
+80
@@ -0,0 +1,80 @@
|
||||
import { mkdtempSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const { mockedExecFile, mockedExecFileAsync } = vi.hoisted(() => {
|
||||
const mockedExecFileAsync = vi.fn();
|
||||
const mockedExecFile = vi.fn();
|
||||
mockedExecFile[Symbol.for("nodejs.util.promisify.custom")] = mockedExecFileAsync;
|
||||
return { mockedExecFile, mockedExecFileAsync };
|
||||
});
|
||||
|
||||
vi.mock("node:child_process", () => ({ execFile: mockedExecFile }));
|
||||
|
||||
import { getExportTools, parseVideoQcOutput } from "../../src/tools/export.js";
|
||||
|
||||
describe("parseVideoQcOutput", () => {
|
||||
it("returns exact black and freeze intervals", () => {
|
||||
const stderr = [
|
||||
"[blackdetect] black_start:0 black_end:1.25 black_duration:1.25",
|
||||
"[freezedetect] lavfi.freezedetect.freeze_start: 2.5",
|
||||
"[freezedetect] lavfi.freezedetect.freeze_duration: 1.5",
|
||||
"[freezedetect] lavfi.freezedetect.freeze_end: 4",
|
||||
].join("\n");
|
||||
expect(parseVideoQcOutput(stderr)).toEqual({
|
||||
blackFrames: [{ start: 0, end: 1.25, duration: 1.25 }],
|
||||
freezes: [{ start: 2.5, end: 4, duration: 1.5 }],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("analyze_video_qc boundary", () => {
|
||||
const tool = getExportTools({ tempDir: "/tmp/test" }).analyze_video_qc;
|
||||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it("rejects invalid thresholds and missing files before FFmpeg", async () => {
|
||||
await expect(tool.handler({ media_path: "missing.mp4", minimum_black_seconds: 0 }))
|
||||
.resolves.toMatchObject({ success: false, error: expect.stringContaining("minimum_black_seconds") });
|
||||
await expect(tool.handler({ media_path: "missing.mp4" }))
|
||||
.resolves.toMatchObject({ success: false, error: expect.stringContaining("not found") });
|
||||
await expect(tool.handler({ media_path: "missing.mp4", minimum_freeze_seconds: 0 }))
|
||||
.resolves.toMatchObject({ success: false, error: expect.stringContaining("minimum_freeze_seconds") });
|
||||
});
|
||||
|
||||
it("reports decoded findings without modifying the delivery file", async () => {
|
||||
const directory = mkdtempSync(join(tmpdir(), "premiere-video-qc-"));
|
||||
const mediaPath = join(directory, "delivery.mp4");
|
||||
writeFileSync(mediaPath, "video-fixture");
|
||||
mockedExecFileAsync.mockResolvedValueOnce({
|
||||
stdout: "",
|
||||
stderr: [
|
||||
"black_start:0 black_end:1.25 black_duration:1.25",
|
||||
"lavfi.freezedetect.freeze_start: 2.5",
|
||||
"lavfi.freezedetect.freeze_end: 4",
|
||||
].join("\n"),
|
||||
});
|
||||
|
||||
await expect(tool.handler({ media_path: mediaPath, minimum_black_seconds: 1, minimum_freeze_seconds: 1 }))
|
||||
.resolves.toMatchObject({
|
||||
success: true,
|
||||
data: {
|
||||
mediaPath,
|
||||
passes: false,
|
||||
blackFrames: [{ start: 0, end: 1.25, duration: 1.25 }],
|
||||
freezes: [{ start: 2.5, end: 4, duration: 1.5 }],
|
||||
},
|
||||
});
|
||||
expect(mockedExecFileAsync).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("preserves a non-timeout FFmpeg failure detail", async () => {
|
||||
const directory = mkdtempSync(join(tmpdir(), "premiere-video-qc-error-"));
|
||||
const mediaPath = join(directory, "delivery.mp4");
|
||||
writeFileSync(mediaPath, "video-fixture");
|
||||
mockedExecFileAsync.mockRejectedValueOnce(Object.assign(new Error("decode failed"), { stderr: "invalid stream" }));
|
||||
|
||||
await expect(tool.handler({ media_path: mediaPath }))
|
||||
.resolves.toMatchObject({ success: false, error: expect.stringContaining("invalid stream") });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user