mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-07 18:26:17 +00:00
fix(studio): preserve alpha proxy playback (#2625)
* fix(studio): preserve alpha proxy playback * test(cli): pin VP8 alpha proxy pre-resolution * fix(studio): emit textarea field-sizing CSS * test(studio): verify textarea CSS generation
This commit is contained in:
@@ -69,7 +69,7 @@ vi.mock("./staticProjectServer.js", () => ({
|
||||
vi.mock("@hyperframes/studio-server/media-codec-map", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("@hyperframes/studio-server/media-codec-map")>()),
|
||||
scanProjectMediaCodecMap: mocks.scanProjectMediaCodecMap,
|
||||
proxyVariantFor: (facts: { hasAlpha?: boolean }) => (facts.hasAlpha ? "vp9" : "h264"),
|
||||
proxyVariantFor: (facts: { hasAlpha?: boolean }) => (facts.hasAlpha ? "vp8" : "h264"),
|
||||
}));
|
||||
vi.mock("@hyperframes/studio-server/proxy-transcoder", () => ({
|
||||
resolveProxy: mocks.resolveProxy,
|
||||
@@ -502,7 +502,7 @@ describe("preResolveHostileMediaProxies", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("does not pre-resolve a hostile asset rejected by the shared proxy policy", async () => {
|
||||
it("pre-resolves an alpha VP9 asset through the Chromium-compatible VP8 proxy", async () => {
|
||||
const projectDir = mkProjectDir();
|
||||
mocks.scanProjectMediaCodecMap.mockResolvedValue({
|
||||
"/alpha.webm": {
|
||||
@@ -515,7 +515,12 @@ describe("preResolveHostileMediaProxies", () => {
|
||||
|
||||
await preResolveHostileMediaProxies(projectDir, "<html></html>");
|
||||
|
||||
expect(mocks.resolveProxy).not.toHaveBeenCalled();
|
||||
expect(mocks.resolveProxy).toHaveBeenCalledTimes(1);
|
||||
expect(mocks.resolveProxy).toHaveBeenCalledWith(
|
||||
projectDir,
|
||||
join(projectDir, "alpha.webm"),
|
||||
"vp8",
|
||||
);
|
||||
});
|
||||
|
||||
it("is a no-op when the codec map has no hostile entries", async () => {
|
||||
|
||||
@@ -49,7 +49,7 @@ vi.mock("@hyperframes/studio-server/proxy-transcoder", () => ({
|
||||
|
||||
vi.mock("@hyperframes/studio-server/media-codec-map", () => ({
|
||||
scanProjectMediaCodecMap: mocks.scanProjectMediaCodecMap,
|
||||
proxyVariantFor: (facts: { hasAlpha?: boolean }) => (facts.hasAlpha ? "vp9" : "h264"),
|
||||
proxyVariantFor: (facts: { hasAlpha?: boolean }) => (facts.hasAlpha ? "vp8" : "h264"),
|
||||
}));
|
||||
|
||||
const { bakeMediaProxies, PROXY_ARCHIVE_PREFIX } = await import("./publishProxyBake.js");
|
||||
@@ -196,7 +196,7 @@ describe("bakeMediaProxies", () => {
|
||||
expect(html).not.toContain("assets/my%20clip.mp4");
|
||||
});
|
||||
|
||||
it("bakes an alpha-bearing hostile asset as a VP9 WebM proxy", async () => {
|
||||
it("bakes an alpha-bearing hostile asset as a VP8 WebM proxy", async () => {
|
||||
mocks.scanProjectMediaCodecMap.mockResolvedValue({
|
||||
"/clip.mov": {
|
||||
codecName: "prores",
|
||||
@@ -205,7 +205,7 @@ describe("bakeMediaProxies", () => {
|
||||
hasAlpha: true,
|
||||
},
|
||||
});
|
||||
const proxyPath = tmpProxyFile("PROXY_VP9_ALPHA_BYTES", ".webm");
|
||||
const proxyPath = tmpProxyFile("PROXY_VP8_ALPHA_BYTES", ".webm");
|
||||
mocks.resolveProxy.mockResolvedValue(proxyPath);
|
||||
const fileContents = new Map<string, Buffer>([
|
||||
["index.html", indexHtml(`<video src="clip.mov" muted></video>`)],
|
||||
@@ -217,13 +217,13 @@ describe("bakeMediaProxies", () => {
|
||||
expect(mocks.resolveProxy).toHaveBeenCalledWith(
|
||||
PROJECT_DIR,
|
||||
join(PROJECT_DIR, "clip.mov"),
|
||||
"vp9",
|
||||
"vp8",
|
||||
);
|
||||
const proxyEntries = [...fileContents.keys()].filter((key) =>
|
||||
key.startsWith(`${PROXY_ARCHIVE_PREFIX}/`),
|
||||
);
|
||||
expect(proxyEntries).toEqual([`${PROXY_ARCHIVE_PREFIX}/proxy.webm`]);
|
||||
expect(fileContents.get(proxyEntries[0]!)?.toString("utf-8")).toBe("PROXY_VP9_ALPHA_BYTES");
|
||||
expect(fileContents.get(proxyEntries[0]!)?.toString("utf-8")).toBe("PROXY_VP8_ALPHA_BYTES");
|
||||
expect(fileContents.get("index.html")?.toString("utf-8")).toContain(proxyEntries[0]!);
|
||||
expect(manifest).toEqual({ proxied: ["/clip.mov"], skippedAlpha: [], failed: [] });
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* `cloud render` never calls this: it builds and zips the file map without an
|
||||
* intermediate baking transform (R2 in the plan).
|
||||
*
|
||||
* Alpha-bearing sources bake as VP9/WebM so transparency survives. A failed
|
||||
* Alpha-bearing sources bake as VP8/WebM so transparency survives. A failed
|
||||
* hostile transcode aborts publish with a
|
||||
* structured manifest rather than silently shipping an unplayable asset.
|
||||
*/
|
||||
@@ -52,7 +52,7 @@ export const PROXY_ARCHIVE_PREFIX = "_proxy";
|
||||
|
||||
export interface ProxyBakeManifest {
|
||||
proxied: string[];
|
||||
/** @deprecated Alpha sources are proxied as VP9; retained as an always-empty compatibility field. */
|
||||
/** @deprecated Alpha sources are proxied as VP8; retained as an always-empty compatibility field. */
|
||||
skippedAlpha: string[];
|
||||
failed: Array<{ path: string; error: string }>;
|
||||
}
|
||||
|
||||
@@ -69,16 +69,16 @@ vi.mock("@hyperframes/studio-server/proxy-transcoder", () => ({
|
||||
vi.mock("@hyperframes/studio-server/media-codec-map", () => ({
|
||||
probeAssetCodec: mocks.probeAssetCodec,
|
||||
decideMediaProxyEligibility: mocks.decideMediaProxyEligibility,
|
||||
isProxyVariant: (value: string) => value === "h264" || value === "vp9",
|
||||
isProxyVariantRequest: (value: string) => value === "auto" || value === "h264" || value === "vp9",
|
||||
proxyVariantFor: (facts: { hasAlpha?: boolean }) => (facts.hasAlpha ? "vp9" : "h264"),
|
||||
resolveProxyVariantRequest: (request: "auto" | "h264" | "vp9", facts: { hasAlpha?: boolean }) => {
|
||||
const expected = facts.hasAlpha ? "vp9" : "h264";
|
||||
isProxyVariant: (value: string) => value === "h264" || value === "vp8",
|
||||
isProxyVariantRequest: (value: string) => value === "auto" || value === "h264" || value === "vp8",
|
||||
proxyVariantFor: (facts: { hasAlpha?: boolean }) => (facts.hasAlpha ? "vp8" : "h264"),
|
||||
resolveProxyVariantRequest: (request: "auto" | "h264" | "vp8", facts: { hasAlpha?: boolean }) => {
|
||||
const expected = facts.hasAlpha ? "vp8" : "h264";
|
||||
return request === "auto" || request === expected ? expected : null;
|
||||
},
|
||||
PROXY_VARIANT_CONFIG: {
|
||||
h264: { extension: ".mp4", contentType: "video/mp4" },
|
||||
vp9: { extension: ".webm", contentType: "video/webm" },
|
||||
vp8: { extension: ".webm", contentType: "video/webm" },
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -311,7 +311,7 @@ describe("serveStaticProjectHtml transparent media proxies", () => {
|
||||
},
|
||||
);
|
||||
|
||||
it("serves an alpha-bearing video through a VP9 WebM proxy", async () => {
|
||||
it("serves an alpha-bearing video through a VP8 WebM proxy", async () => {
|
||||
const projectDir = mk();
|
||||
writeFileSync(join(projectDir, "clip.mov"), "prores-4444-alpha-bytes");
|
||||
mocks.probeAssetCodec.mockResolvedValueOnce({
|
||||
@@ -321,7 +321,7 @@ describe("serveStaticProjectHtml transparent media proxies", () => {
|
||||
representativeMime: null,
|
||||
});
|
||||
const proxyPath = join(projectDir, "proxy.webm");
|
||||
writeFileSync(proxyPath, "vp9-alpha-proxy");
|
||||
writeFileSync(proxyPath, "vp8-alpha-proxy");
|
||||
mocks.resolveProxy.mockResolvedValueOnce(proxyPath);
|
||||
server = await serveStaticProjectHtml(projectDir, "<html></html>");
|
||||
|
||||
@@ -333,7 +333,7 @@ describe("serveStaticProjectHtml transparent media proxies", () => {
|
||||
expect(mocks.resolveProxy).toHaveBeenCalledWith(
|
||||
projectDir,
|
||||
join(projectDir, "clip.mov"),
|
||||
"vp9",
|
||||
"vp8",
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user