MCPcopy Create free account
hub / github.com/heygen-com/hyperframes / syncMediaForCurrentState

Function syncMediaForCurrentState

packages/core/src/runtime/init.ts:1657–1771  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

1655 };
1656
1657 const syncMediaForCurrentState = () => {
1658 const resolveMediaCompositionContext = (element: HTMLVideoElement | HTMLAudioElement) => {
1659 const compositionRoot = element.closest("[data-composition-id]");
1660 const inheritedStart = compositionRoot ? resolveStartForElement(compositionRoot, 0) : null;
1661 // Media sync follows the authored host window, matching visibility for
1662 // authored composition hosts. Live child timeline duration only fills in
1663 // when no authored timing exists, so seeks clamp against host clip timing.
1664 const inheritedDuration = compositionRoot
1665 ? resolveDurationForElement(compositionRoot, { includeAuthoredTimingAttrs: true })
1666 : null;
1667 return { compositionRoot, inheritedStart, inheritedDuration };
1668 };
1669 const cache = refreshRuntimeMediaCache({
1670 shouldIncludeElement: (element) =>
1671 element.hasAttribute("data-start") ||
1672 Boolean(resolveMediaCompositionContext(element).compositionRoot),
1673 resolveStartSeconds: (element) => {
1674 const context = resolveMediaCompositionContext(
1675 element as HTMLVideoElement | HTMLAudioElement,
1676 );
1677 return resolveMediaStartSeconds(element, context.inheritedStart ?? 0);
1678 },
1679 resolveDurationSeconds: (element) => {
1680 const context = resolveMediaCompositionContext(element);
1681 const start = resolveMediaStartSeconds(element, context.inheritedStart ?? 0);
1682 const mediaStart =
1683 Number.parseFloat(element.dataset.playbackStart ?? element.dataset.mediaStart ?? "0") ||
1684 0;
1685 const hostRemaining =
1686 context.inheritedStart != null &&
1687 context.inheritedDuration != null &&
1688 context.inheritedDuration > 0
1689 ? Math.max(0, context.inheritedStart + context.inheritedDuration - start)
1690 : null;
1691 const sourceDuration =
1692 Number.isFinite(element.duration) && element.duration > mediaStart
1693 ? Math.max(0, element.duration - mediaStart)
1694 : null;
1695 // The element's own data-duration is an explicit clip-length trim
1696 // (the studio writes it when you drag the clip edge). It must bound
1697 // playback so a trimmed track stops at its edge instead of running on
1698 // to the source-file or host-composition end. Absent → no cap (an
1699 // untrimmed clip plays its natural source length).
1700 const ownDuration = Number.parseFloat(element.dataset.duration ?? "");
1701 const explicitDuration =
1702 Number.isFinite(ownDuration) && ownDuration > 0 ? ownDuration : null;
1703 const candidates = [sourceDuration, hostRemaining, explicitDuration].filter(
1704 (value): value is number => value != null,
1705 );
1706 return candidates.length > 0 ? Math.min(...candidates) : null;
1707 },
1708 });
1709 // Attach probed volume keyframes to clips so syncRuntimeMedia can use the
1710 // same envelope the renderer uses instead of tracking GSAP-change diffs.
1711 for (const clip of cache.mediaClips) {
1712 const kf = volumeKeyframeCache.get(clip.el as HTMLMediaElement);
1713 if (kf) clip.volumeKeyframes = kf;
1714 }

Callers 2

transportTickFunction · 0.85

Calls 15

refreshRuntimeMediaCacheFunction · 0.90
syncRuntimeMediaFunction · 0.90
postRuntimeMessageFunction · 0.90
resolveMediaStartSecondsFunction · 0.85
isTimedElementVisibleAtFunction · 0.85
isTimedClipInFlowFunction · 0.85
isTimedClipLeafFunction · 0.85
getMethod · 0.80
isActiveMethod · 0.80
ownsElementMethod · 0.80

Tested by

no test coverage detected