/**
 * Helpers shared between the distributed activity scripts (`plan.ts`,
 * `renderChunk.ts`, `assemble.ts`). Kept module-local so the public surface
 * stays just the three activity functions plus their result types.
 */
import { type Fps } from "@hyperframes/core";
import { type VideoElement, type VideoFrameFormat, type VideoMetadata } from "@hyperframes/engine";
import { type RenderConfig, type RenderJob } from "../renderOrchestrator.js";
import { type ProducerLogger } from "../../logger.js";
/**
 * Output container formats the distributed pipeline supports end-to-end.
 * Single source of truth for the format union — `plan()`, `renderChunk()`,
 * `assemble()`, the aws-lambda handler, and the harness all derive from
 * this type. Adding a new format starts here.
 */
export type DistributedFormat = "mp4" | "mov" | "png-sequence" | "webm";
/**
 * Filename of the per-video extraction manifest written by `plan()` into
 * `<planDir>/meta/` and consumed by `renderChunk()` to rebuild the
 * BeforeCaptureHook that injects pre-extracted frames into the page.
 * Absence is fine — compositions with no `<video>` elements never
 * produce the file.
 */
export declare const PLAN_VIDEOS_META_RELATIVE_PATH = "meta/videos.json";
/**
 * Relative path of the normalized audio artifact written into a distributed
 * plan. Keep writers and transport readers coupled through this contract
 * rather than duplicating a filename literal.
 *
 * Derived from the engine's filename rather than restated, because the
 * extension selects the muxer: the plan artifact is the mix moved into place,
 * so if the two ever disagreed the plan would claim a container the file
 * doesn't have.
 */
export declare const PLAN_AUDIO_RELATIVE_PATH = "audio.m4a";
/**
 * Name the audio artifact carried before it moved to an MP4-family container.
 *
 * COMPATIBILITY SHIM, remove one release after the container change ships.
 * `plan` and `assemble` are separate invocations bridged by object storage, so
 * a rolling deploy can pair a pre-rollout planner with a post-rollout
 * assembler. Both readers locate the artifact by existence alone, which makes
 * that pairing a silently muted video rather than an error, so reads accept the
 * old name for one release while writes only ever emit the new one.
 */
export declare const PLAN_AUDIO_LEGACY_RELATIVE_PATH = "audio.aac";
/** True for either the current or the legacy plan-audio artifact name. */
export declare function isPlanAudioArtifactPath(path: string): boolean;
/**
 * Locate a plan's audio artifact on disk, preferring the current name and
 * falling back to the legacy one. Returns `null` when the plan has no audio.
 */
export declare function resolvePlanAudioPath(planDir: string): string | null;
/**
 * On-disk shape of `<planDir>/meta/videos.json`. The engine's
 * `ExtractedFrames` shape carries an absolute `outputDir`, a `framePaths`
 * Map, and potentially an open file descriptor — none of those survive
 * a serialize → re-deserialize round trip across processes. The
 * serialized form keeps only what plan-time produced; `renderChunk` re-
 * derives `outputDir` (always `<planDir>/video-frames/<videoId>`) and
 * `framePaths` (re-listed from that directory) when reconstructing the
 * `FrameLookupTable`.
 */
export interface PlanVideosJson {
    videos: VideoElement[];
    extracted: Array<{
        videoId: string;
        srcPath: string;
        framePattern: string;
        fps: number;
        totalFrames: number;
        metadata: VideoMetadata;
    }>;
}
export declare const INVALID_VIDEO_METADATA: "INVALID_VIDEO_METADATA";
/**
 * Typed failure for the cross-process `meta/videos.json` contract.
 *
 * Plan v1 and Plan v2 share this metadata. Keeping the validation error in
 * this storage-neutral module lets the v1 chunk reader fail closed while the
 * v2 converter can wrap it in its own integrity-error contract.
 */
export declare class PlanVideosMetadataError extends Error {
    readonly code: "INVALID_VIDEO_METADATA";
    constructor(message: string);
}
/**
 * Parse the untrusted on-disk `meta/videos.json` shape used by both plan
 * protocols. In addition to field types, require a one-to-one relationship
 * between declared videos and extracted-frame metadata: a distributed render
 * cannot safely fall back to native remote video decoding when extraction
 * failed on the planner.
 */
export declare function parsePlanVideosJson(value: unknown): PlanVideosJson;
/**
 * Build the shared v1/v2 video metadata contract.
 *
 * Successful extraction normally replaces an open-ended video's `Infinity`
 * with its finite natural source end. If duration probing/extraction could not
 * derive that natural end, the last safe timing boundary is the already
 * validated composition end. Authored finite ends are copied unchanged.
 */
export declare function buildPlanVideosJson(input: {
    videos: readonly VideoElement[];
    extracted: PlanVideosJson["extracted"];
    compositionEnd: number;
}): PlanVideosJson;
/**
 * Read `ffmpeg -version` first line. The string is opaque — `planHash`
 * mixes it in verbatim, so any drift across worker hosts trips a
 * `FFMPEG_VERSION_MISMATCH` rather than producing pixels that subtly
 * disagree with the plan's baked-in encoder args.
 */
export declare function readFfmpegVersion(): Promise<string>;
/**
 * Inputs for {@link buildSyntheticRenderJob}. The two distributed activity
 * scripts (`plan.ts`, `renderChunk.ts`) reach for slightly different
 * sources — caller config vs. frozen `LockedRenderConfig` — but the
 * resulting `RenderJob` shape is identical, so the helper accepts both.
 */
export interface SyntheticRenderJobInput {
    fps: Fps;
    format: RenderConfig["format"];
    quality: RenderConfig["quality"];
    crf?: number;
    bitrate?: string;
    videoFrameFormat?: VideoFrameFormat;
    outputResolution?: RenderConfig["outputResolution"];
    outputResolutionAspectAgnostic?: RenderConfig["outputResolutionAspectAgnostic"];
    hdrMode: RenderConfig["hdrMode"];
    strictness?: RenderConfig["strictness"];
    entryFile: string;
    logger?: ProducerLogger;
    producerConfig?: RenderConfig["producerConfig"];
    /** Render-time overrides consumed by the plan browser probe. */
    variables?: RenderConfig["variables"];
}
/**
 * Synthesize a `RenderJob` from a distributed-render config. The distributed
 * activities operate without a full `RenderJob` (they're stateless workers),
 * so we build one to feed the existing stage interfaces.
 */
export declare function buildSyntheticRenderJob(input: SyntheticRenderJobInput): RenderJob;
export declare function readProducerVersion(): string;
//# sourceMappingURL=shared.d.ts.map