mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 06:30:03 +00:00
fix(engine,producer,lint): resolve <source> children for media extract and localize (#3238)
Parent src-only scans skipped multi-format <video>/<audio> markup, so those elements were never extracted, downloaded, or mixed and rendered blank/silent. Lint now accepts a child <source src> as a resolvable media src.
This commit is contained in:
@@ -1574,6 +1574,25 @@ describe("localizeRemoteMediaSources", () => {
|
||||
expect(remoteMediaAssets.size).toBe(0);
|
||||
});
|
||||
|
||||
it("localizes remote <source> children of a <video>", async () => {
|
||||
const orig = globalThis.fetch;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(globalThis as any).fetch = async () => validTestMediaResponse();
|
||||
try {
|
||||
const dl = mkdtempSync(join(tmpdir(), "hf-dl-src-"));
|
||||
const html = `<video id="rec" data-start="0" data-end="5" muted>
|
||||
<source src="https://src-ok.example.com/rec.mp4" type="video/mp4">
|
||||
<source src="https://src-ok.example.com/rec.webm" type="video/webm">
|
||||
</video>`;
|
||||
const { html: result, remoteMediaAssets } = await localizeRemoteMediaSources(html, dl);
|
||||
expect(result).not.toContain("https://src-ok.example.com/");
|
||||
expect(remoteMediaAssets.size).toBe(2);
|
||||
} finally {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(globalThis as any).fetch = orig;
|
||||
}
|
||||
});
|
||||
|
||||
it("rewrites src in both double-quoted and single-quoted attributes", async () => {
|
||||
const orig = globalThis.fetch;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
@@ -1280,6 +1280,8 @@ const REMOTE_MEDIA_SUBDIR = "_remote_media";
|
||||
// have `>` inside quoted attribute values (data-title etc.).
|
||||
const REMOTE_MEDIA_TAG_RE =
|
||||
/<(?:video|audio)\b[^>]*?\bsrc\s*=\s*["'](https?:\/\/[^"']+)["'][^>]*>/gi;
|
||||
// <source src> on media elements (picture uses srcset, not src).
|
||||
const REMOTE_SOURCE_TAG_RE = /<source\b[^>]*?\bsrc\s*=\s*["'](https?:\/\/[^"']+)["'][^>]*>/gi;
|
||||
// Match <img> tags (including agent-pipeline-emitted variants where `src` is
|
||||
// not the first attribute). Producer-side localisation is the primary fix for
|
||||
// the remote-<img> flicker; frameCapture's `pollImagesReady`/`decodeAllImages`
|
||||
@@ -1350,10 +1352,11 @@ async function downloadAndRewriteUrls(
|
||||
}
|
||||
|
||||
/**
|
||||
* Download any remote `src` URLs on `<video>` and `<audio>` elements into a
|
||||
* local subdirectory of `downloadDir`, rewrite the HTML src attributes to
|
||||
* relative paths, and return the updated HTML along with a map of
|
||||
* `{ relativePath → absoluteLocalPath }` for callers to add to `externalAssets`.
|
||||
* Download any remote `src` URLs on `<video>` / `<audio>` elements and their
|
||||
* `<source>` children into a local subdirectory of `downloadDir`, rewrite the
|
||||
* HTML src attributes to relative paths, and return the updated HTML along with
|
||||
* a map of `{ relativePath → absoluteLocalPath }` for callers to add to
|
||||
* `externalAssets`.
|
||||
*
|
||||
* Skips URLs that fail to download (warns and preserves the original URL so
|
||||
* the browser can still attempt the remote fetch as a fallback).
|
||||
@@ -1369,12 +1372,13 @@ export async function localizeRemoteMediaSources(
|
||||
html: string,
|
||||
downloadDir: string,
|
||||
): Promise<{ html: string; remoteMediaAssets: Map<string, string> }> {
|
||||
// Collect unique HTTP URLs from <video>/<audio> src attributes.
|
||||
const urlSet = new Set<string>();
|
||||
const re = new RegExp(REMOTE_MEDIA_TAG_RE.source, REMOTE_MEDIA_TAG_RE.flags);
|
||||
let m: RegExpExecArray | null;
|
||||
while ((m = re.exec(html)) !== null) {
|
||||
if (m[1]) urlSet.add(m[1]);
|
||||
for (const tagRe of [REMOTE_MEDIA_TAG_RE, REMOTE_SOURCE_TAG_RE]) {
|
||||
const re = new RegExp(tagRe.source, tagRe.flags);
|
||||
let m: RegExpExecArray | null;
|
||||
while ((m = re.exec(html)) !== null) {
|
||||
if (m[1]) urlSet.add(m[1]);
|
||||
}
|
||||
}
|
||||
return downloadAndRewriteUrls(
|
||||
urlSet,
|
||||
|
||||
Reference in New Issue
Block a user