diff --git a/packages/aws-lambda/src/sdk/deploySite.test.ts b/packages/aws-lambda/src/sdk/deploySite.test.ts index bd041bd10d..6634bd24cf 100644 --- a/packages/aws-lambda/src/sdk/deploySite.test.ts +++ b/packages/aws-lambda/src/sdk/deploySite.test.ts @@ -6,7 +6,7 @@ import { join } from "node:path"; import { createHash } from "node:crypto"; import type { S3Client } from "@aws-sdk/client-s3"; import { AUDIO_SIDECAR_MIN_BYTES } from "@hyperframes/producer/distributed"; -import { audioSidecarUri } from "../contentStore.js"; +import { audioSidecarUri, probeFactsUri } from "../contentStore.js"; import { parseSiteManifest } from "../siteManifest.js"; import { asS3Client, FakeS3 } from "./__fixtures__/fakeS3.js"; import { deploySite } from "./deploySite.js"; @@ -275,3 +275,52 @@ describe.skipIf(!HAS_FFMPEG)("deploySite audio sidecars", { timeout: 60_000 }, ( expect(notices[0]).toContain("ffmpeg"); }); }); + +describe.skipIf(!HAS_FFMPEG)("deploySite probe facts", { timeout: 60_000 }, () => { + function addVideo(): void { + const made = spawnSync(FFMPEG, [ + ...["-v", "error", "-y", "-f", "lavfi", "-i", "testsrc2=size=64x64:rate=25:duration=2"], + ...["-c:v", "mpeg4", join(projectDir, "assets", "take.mp4")], + ]); + expect(made.status).toBe(0); + } + + it("stores each video's ffprobe JSON beside it, and leaves the site's file list as it was", async () => { + addVideo(); + const s3 = new FakeS3(); + const site = await deploySite({ projectDir, bucketName: "test-bucket", s3: asS3Client(s3) }); + + const take = parseSiteManifest( + s3.bodies.get(`test-bucket/sites/${site.siteId}/files.json`)?.toString() ?? "", + ).find((file) => file.path === "assets/take.mp4"); + const facts = probeFactsUri("test-bucket", take?.sha256 ?? "").replace("s3://", ""); + expect(JSON.parse(s3.bodies.get(facts)?.toString() ?? "{}").streams[0].codec_type).toBe("video"); + expect(sitePaths(s3, site.siteId)).toEqual([ + "assets/style.css", + "assets/take.mp4", + "index.html", + ]); + }); + + it("deploys the same site with no probe stored when there is no ffprobe, and says so", async () => { + addVideo(); + const notices: string[] = []; + const before = process.env.HYPERFRAMES_FFPROBE_PATH; + process.env.HYPERFRAMES_FFPROBE_PATH = join(scratch, "no-such-ffprobe"); + const s3 = new FakeS3(); + try { + await deploySite({ + projectDir, + bucketName: "test-bucket", + s3: asS3Client(s3), + onNotice: (message) => notices.push(message), + }); + } finally { + if (before === undefined) delete process.env.HYPERFRAMES_FFPROBE_PATH; + else process.env.HYPERFRAMES_FFPROBE_PATH = before; + } + + expect([...s3.existing].filter((id) => id.endsWith(".probe.v1.json"))).toEqual([]); + expect(notices.some((message) => message.includes("ffprobe"))).toBe(true); + }); +}); diff --git a/packages/aws-lambda/src/siteManifest.test.ts b/packages/aws-lambda/src/siteManifest.test.ts index 87b4386576..f8994093d4 100644 --- a/packages/aws-lambda/src/siteManifest.test.ts +++ b/packages/aws-lambda/src/siteManifest.test.ts @@ -3,7 +3,7 @@ import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { S3Client } from "@aws-sdk/client-s3"; -import { audioSidecarUri, contentStoreUri } from "./contentStore.js"; +import { audioSidecarUri, contentStoreUri, probeFactsUri } from "./contentStore.js"; import { FakeS3 } from "./sdk/__fixtures__/fakeS3.js"; import { downloadSiteFiles, serializeSiteManifest, siteManifestUri } from "./siteManifest.js"; @@ -70,4 +70,19 @@ describe("downloadSiteFiles", () => { expect(remote["takes/camera.mov"]?.url).toBeString(); expect(remote["takes/camera.mov"]?.audioSidecarUrl).toBeUndefined(); }); + + it("hands a remote video's stored probe along with it, when one is stored", async () => { + const fake = new FakeS3(); + const manifestUri = siteWithVideo(fake); + fake.existing.add(probeFactsUri("bucket", VIDEO_SHA).replace("s3://", "")); + + const remote = await downloadSiteFiles( + clientOver(fake), + manifestUri, + join(dir, "project"), + true, + ); + + expect(remote["takes/camera.mov"]?.probeFactsUrl).toContain(`${VIDEO_SHA}.probe.v1.json`); + }); });