import {z} from 'zod' export type GetApiV1VideosIdTimelineArgs = {id: string, clipIds?: string | undefined, include?: string | undefined}; export type GetApiV1VideosIdTimelineOptions = {baseUrl?: string | undefined, BearerAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const timelineContentCounts = z.object({blurs: z.number().int().gte(0).lte(9007199254740991), cuts: z.number().int().gte(0).lte(9007199254740991), highlights: z.number().int().gte(0).lte(9007199254740991), layouts: z.number().int().gte(0).lte(9007199254740991), overlays: z.number().int().gte(0).lte(9007199254740991), soundEffects: z.number().int().gte(0).lte(9007199254740991), textOverlays: z.number().int().gte(0).lte(9007199254740991), transcriptWords: z.number().int().gte(0).lte(9007199254740991).nullable(), zooms: z.number().int().gte(0).lte(9007199254740991)}); export const timelineClip = z.object({contents: timelineContentCounts, durationMs: z.number().gte(0), id: z.string(), name: z.string(), order: z.number().int().gte(-9007199254740991).lte(9007199254740991), timelineStartMs: z.number().gte(0)}); export const clipBackgroundOutput = z.object({color: z.string().nullable().optional(), gradientAngle: z.number().int().gte(-9007199254740991).lte(9007199254740991).nullable().optional(), gradientColor1: z.string().nullable().optional(), gradientColor2: z.string().nullable().optional(), imageUrl: z.string().nullable().optional(), shaderGradientPreset: z.string().nullable().optional(), sourceId: z.string().nullable().optional(), type: z.enum(["solid", "gradient", "image", "video", "shaderGradient", "ambient"]), videoDurationSeconds: z.number().gte(0).nullable().optional(), videoUrl: z.string().nullable().optional()}); export const maskDimensionsOutput = z.object({heightPct: z.number().gte(0).lte(100), widthPct: z.number().gte(0).lte(100)}); export const maskPointOutput = z.object({xPct: z.number().gte(0).lte(100), yPct: z.number().gte(0).lte(100)}); export const transitionStyle = z.enum(["smooth", "hard_cut"]); export const clipMask = z.object({dimensions: maskDimensionsOutput, durationMs: z.number().gte(0), id: z.string(), intensity: z.number().gte(0).lte(1), point: maskPointOutput, startTimeMs: z.number().gte(0), transition: transitionStyle, type: z.enum(["blur", "highlight"])}); export const cutOutput = z.object({durationMs: z.number().int().gt(0).lte(9007199254740991), startTimeMs: z.number().int().gte(0).lte(9007199254740991)}); export const layoutSceneType = z.enum(["basicSubject", "cameraSubject", "combi"]); export const clipLayoutCropOutput = z.object({bottom: z.number().gte(0), left: z.number().gte(0), right: z.number().gte(0), top: z.number().gte(0)}); export const customLayoutDimensions = z.object({height: z.number().gt(0), width: z.number().gt(0)}); export const customLayoutPoint = z.object({x: z.number(), y: z.number()}); export const customLayoutSlot = z.object({corners: z.enum(["none", "regular", "squircle"]).optional(), dimensions: customLayoutDimensions.optional(), hidden: z.boolean().optional(), order: z.number().int().gte(-9007199254740991).lte(9007199254740991).optional(), point: customLayoutPoint.optional(), shape: z.enum(["none", "circle", "square", "portrait", "cutout", "blob", "blob-outline"]).optional()}); export const clipLayoutShape = z.discriminatedUnion("kind", [z.object({kind: z.literal("fullscreen"), screenFit: z.enum(["cover", "letterbox"]).optional(), style: z.enum(["regular", "stretch"]).optional()}), z.object({kind: z.literal("middle"), shape: z.enum(["circle", "square", "landscape", "portrait"]).optional()}), z.object({kind: z.literal("side-by-side"), position: z.enum(["left", "right", "top", "bottom"]), size: z.enum(["S", "M", "L"]).optional(), style: z.enum(["regular", "even", "overlap", "perspective"])}), z.object({kind: z.literal("tv-presenter"), position: z.enum(["left", "right"]), style: z.enum(["regular", "full", "overlap"])}), z.object({kind: z.literal("cut-out"), position: z.enum(["left", "right"]).optional(), style: z.enum(["regular", "perspective"]).optional()}), z.object({kind: z.literal("camera-bubble"), position: z.enum(["left", "right", "top", "bottom", "top-left", "top-right", "bottom-left", "bottom-right", "middle"]), screenFit: z.enum(["cover", "letterbox"]).optional(), shape: z.enum(["circle", "square", "landscape", "portrait"]).optional(), size: z.enum(["S", "M", "L"]), style: z.enum(["regular", "full"]).optional()}), z.object({kind: z.literal("camera-only"), punchIn: z.boolean().optional(), shape: z.enum(["circle", "square", "landscape", "portrait"]).optional(), style: z.enum(["fullscreen", "middle"])}), z.object({kind: z.literal("screen-only"), screenFit: z.enum(["cover", "letterbox"]).optional(), style: z.enum(["fullscreen", "middle"])}), z.object({kind: z.literal("custom"), presentation: customLayoutSlot.optional(), subject: customLayoutSlot.optional()})]); export const clipMediaItem = z.object({documentId: z.string().optional(), height: z.number().int().gte(-9007199254740991).lte(9007199254740991).nullable().optional(), imageUrl: z.string().nullable().optional(), muted: z.boolean().nullable().optional(), slot: z.enum(["screen", "camera"]).optional(), sourceId: z.string().nullable().optional(), startTimeMs: z.number().nullable().optional(), type: z.enum(["image", "video", "motion"]), width: z.number().int().gte(-9007199254740991).lte(9007199254740991).nullable().optional()}); export const clipPopOut = z.object({amount: z.number().gte(0).lte(0.5).optional(), background: z.enum(["original", "color"]).optional(), color: z.string().optional(), outlineColor: z.string().optional(), outlineWidth: z.number().gte(0).lte(0.05).optional()}); export const layoutTransitionStyle = z.enum(["spring", "hardCut"]); export const clipLayout = z.object({cameraStyle: z.enum(["none", "circle", "square", "portrait", "cutout", "blob", "blob-outline"]).optional(), crop: clipLayoutCropOutput.nullable().optional(), durationMs: z.number().gte(0).nullable().optional(), followsBase: z.boolean().optional(), id: z.string(), layout: clipLayoutShape.nullable().optional(), media: z.array(clipMediaItem), popOut: clipPopOut.nullable().optional(), startTimeMs: z.number().gte(0).nullable().optional(), transitionStyle: layoutTransitionStyle.nullable().optional()}); export const overlayAnimationCurve = z.enum(["linear", "smooth", "natural", "slow_down", "accelerate", "elastic", "bounce", "overshoot", "impulse", "swing", "custom", "spring"]); export const overlayAnimationSpringOutput = z.object({damping: z.number().gte(1).lte(300), mass: z.number().gte(0.1).lte(10), stiffness: z.number().gte(1).lte(1000)}); export const overlayAnimationEasing = z.object({bezier: z.array(z.union([z.number().gte(0).lte(1), z.number(), z.number().gte(0).lte(1), z.number()])).optional(), curve: overlayAnimationCurve, intensity: z.number().gte(0).lte(1), spring: overlayAnimationSpringOutput.optional()}); export const overlayAnimationPreset = z.enum(["fade", "slide_up", "slide_down", "slide_left", "slide_right", "mask_up", "mask_down", "grow", "shrink", "blur", "blur_slide_up"]); export const overlayAnimationText = z.object({delayMs: z.number().int().gte(0).lte(2000), order: z.enum(["forward", "backward", "center", "edges", "random"]), smoothing: z.enum(["linear", "smooth", "natural", "slow_down", "accelerate", "elastic", "overshoot", "impulse", "swing"]), unit: z.enum(["letters", "words", "lines"])}); export const overlayAnimationSide = z.object({blur: z.number(), clip: z.boolean(), durationMs: z.number().int().gte(-9007199254740991).lte(9007199254740991), easing: overlayAnimationEasing, moveX: z.number(), moveY: z.number(), opacity: z.number(), preset: overlayAnimationPreset.nullable(), rotate: z.number(), scale: z.number(), text: overlayAnimationText.optional()}); export const overlayAnimation = z.object({intro: overlayAnimationSide.nullable(), motionBlur: z.boolean(), outro: overlayAnimationSide.nullable(), textIntro: overlayAnimationSide.nullable(), textOutro: overlayAnimationSide.nullable()}); export const overlayDepth = z.enum(["front", "behind_presenter"]); export const overlayDepthChanges = z.array(z.object({atMs: z.number().gte(0), depth: overlayDepth})); export const overlayDimensionsOutput = z.object({height: z.number().gt(0), width: z.number().gt(0)}); export const overlayPointOutput = z.object({xPct: z.number(), yPct: z.number()}); export const overlayZIndex = z.number().int().gte(0).lte(9007199254740991); export const clipOverlay = z.object({animation: overlayAnimation.nullable(), depth: overlayDepth, depthChanges: overlayDepthChanges.optional(), dimensions: overlayDimensionsOutput, durationMs: z.number().gte(0), id: z.string(), imageUrl: z.string().nullable().optional(), motionDocumentId: z.string().optional(), name: z.string().nullable().optional(), point: overlayPointOutput, sourceId: z.string().nullable().optional(), startTimeMs: z.number().gte(0), transition: transitionStyle, type: z.enum(["image", "video", "motion"]), zIndex: overlayZIndex}); export const clipSoundEffect = z.object({durationMs: z.number().gte(0), id: z.string(), name: z.string().nullable().optional(), sourceId: z.string().nullable().optional(), startTimeMs: z.number().gte(0), volume: z.number()}); export const textOverlayBackgroundOutput = z.object({color: z.string(), type: z.literal("solid")}); export const textOverlayBackgroundPadding = z.number().gte(0).lte(1); export const textOverlayBackgroundShape = z.enum(["none", "regular", "squircle"]); export const textOverlayLetterSpacing = z.number().gte(-0.2).lte(1); export const textOverlayOutline = z.string().nullable(); export const textOverlayShadow = z.enum(["none", "subtle", "deep"]); export const textOverlayTextAlign = z.enum(["left", "center", "right"]); export const clipTextOverlay = z.object({animation: overlayAnimation.nullable(), background: textOverlayBackgroundOutput, backgroundPadding: textOverlayBackgroundPadding, backgroundShape: textOverlayBackgroundShape, color: z.string(), depth: overlayDepth, depthChanges: overlayDepthChanges.optional(), dimensions: overlayDimensionsOutput, durationMs: z.number().gte(0), fontFamily: z.string(), fontId: z.string().optional(), fontSize: z.number().gt(0), fontWeight: z.number(), fontWidth: z.number(), id: z.string(), letterSpacing: textOverlayLetterSpacing, outline: textOverlayOutline, point: overlayPointOutput, shadow: textOverlayShadow, startTimeMs: z.number().gte(0), text: z.string(), textAlign: textOverlayTextAlign, transition: transitionStyle, zIndex: overlayZIndex}); export const timelineTranscript = z.object({text: z.string(), wordCount: z.number().int().gte(0).lte(9007199254740991)}).nullable(); export const transcriptWord = z.object({breakAfter: z.boolean(), endTimeMs: z.number().gte(0), hidden: z.boolean(), index: z.number().int().gte(0).lte(9007199254740991), keepWithNext: z.boolean(), startTimeMs: z.number().gte(0), text: z.string()}); export const zoomFocusPointOutput = z.object({xPct: z.number().gte(0).lte(100), yPct: z.number().gte(0).lte(100)}); export const clipZoom = z.object({durationMs: z.number().gte(0), focusPoint: zoomFocusPointOutput.nullable().optional(), id: z.string(), introTransition: transitionStyle, outroTransition: transitionStyle, scale: z.number().gte(1).lte(3.5).nullable().optional(), startTimeMs: z.number().gte(0), type: z.enum(["manualZoom", "trackingZoom"])}); export const timelineClipDetails = z.object({background: clipBackgroundOutput.optional(), blurs: z.array(clipMask).optional(), clipId: z.string(), cuts: z.array(cutOutput).optional(), highlights: z.array(clipMask).optional(), layoutSceneType: layoutSceneType.optional(), layouts: z.array(clipLayout).optional(), microphoneVolume: z.number().gte(0).lte(2).nullable().optional(), overlays: z.array(clipOverlay).optional(), soundEffects: z.array(clipSoundEffect).optional(), studioSound: z.boolean().optional(), systemAudioVolume: z.number().gte(0).lte(2).nullable().optional(), textOverlays: z.array(clipTextOverlay).optional(), transcript: timelineTranscript.optional(), words: z.array(transcriptWord).nullable().optional(), zooms: z.array(clipZoom).optional()}); export const backgroundMusic = z.object({durationMs: z.number().gt(0), name: z.string().nullable(), url: z.string(), volume: z.number().gte(0).lte(1)}); export const chapter = z.object({description: z.string().max(5000), timestampSeconds: z.number().gte(0), title: z.string().min(1).max(255)}); export const videoCallToActionOutput = z.object({label: z.string().min(1).max(100), url: z.string()}); export const captionFontFamily = z.string().min(1); export const captionFontSize = z.number().gte(40).lte(200); export const captionFontWeight = z.number().gte(100).lte(1000); export const captionLinesPerBlock = z.number().int().gte(0).lte(3); export const captionPosition = z.object({x: z.number().gte(0).lte(1), y: z.number().gte(0).lte(1)}); export const captionStyle = z.discriminatedUnion("name", [z.object({activeWordTextColor: z.string().optional(), backgroundColor: z.string(), backgroundEnabled: z.boolean().optional(), backgroundPadding: z.number().gte(0).lte(1).optional(), highlightColor: z.string().optional(), highlightMode: z.enum(["text", "background", "fadeRest"]).optional(), name: z.literal("backdrop"), outlineColor: z.string().optional(), outlineEnabled: z.boolean().optional(), shadowColor: z.string().optional(), shadowEnabled: z.boolean().optional(), textCase: z.enum(["original", "uppercase", "lowercase"]).optional(), textColor: z.string(), wordLevelHighlights: z.boolean()}), z.object({backgroundColor: z.string().optional(), backgroundEnabled: z.boolean().optional(), backgroundPadding: z.number().gte(0).lte(1).optional(), highlightColor: z.string(), highlightMode: z.enum(["text", "background", "fadeRest"]).optional(), name: z.literal("highlight"), outlineColor: z.string().optional(), outlineEnabled: z.boolean().optional(), primaryTextColor: z.string(), secondaryTextColor: z.string(), shadowColor: z.string().optional(), shadowEnabled: z.boolean().optional(), textCase: z.enum(["original", "uppercase", "lowercase"]).optional(), wordLevelHighlights: z.boolean().optional()}), z.object({activeWordTextColor: z.string().optional(), backgroundColor: z.string().optional(), backgroundEnabled: z.boolean().optional(), backgroundPadding: z.number().gte(0).lte(1).optional(), highlightColor: z.string(), highlightMode: z.enum(["text", "background", "fadeRest"]).optional(), name: z.literal("mono"), outlineColor: z.string().optional(), outlineEnabled: z.boolean().optional(), shadowColor: z.string().optional(), shadowEnabled: z.boolean().optional(), textCase: z.enum(["original", "uppercase", "lowercase"]).optional(), textColor: z.string(), wordLevelHighlights: z.boolean().optional()}), z.object({activeWordTextColor: z.string().optional(), backgroundColor: z.string().optional(), backgroundEnabled: z.boolean().optional(), backgroundPadding: z.number().gte(0).lte(1).optional(), highlightColor: z.string().optional(), highlightMode: z.enum(["text", "background", "fadeRest"]).optional(), name: z.literal("cannes"), outlineColor: z.string().optional(), outlineEnabled: z.boolean().optional(), shadowColor: z.string(), shadowEnabled: z.boolean().optional(), textCase: z.enum(["original", "uppercase", "lowercase"]).optional(), textColor: z.string(), wordLevelHighlights: z.boolean().optional()}), z.object({activeWordTextColor: z.string().optional(), backgroundColor: z.string().optional(), backgroundEnabled: z.boolean().optional(), backgroundPadding: z.number().gte(0).lte(1).optional(), highlightColor: z.string().optional(), highlightMode: z.enum(["text", "background", "fadeRest"]).optional(), name: z.literal("classic"), outlineColor: z.string(), outlineEnabled: z.boolean().optional(), shadowColor: z.string().optional(), shadowEnabled: z.boolean().optional(), textCase: z.enum(["original", "uppercase", "lowercase"]).optional(), textColor: z.string(), wordLevelHighlights: z.boolean().optional()})]); export const cursorStyle = z.enum(["mac", "macTahoe", "macGoldenGate", "windows", "touch"]); export const cursorSettings = z.object({clickRipple: z.boolean(), hideWhenInactive: z.boolean(), returnToStart: z.boolean(), size: z.number().gte(0.5).lte(6), smoothing: z.boolean(), style: cursorStyle, tilt: z.boolean(), tiltStrength: z.number().gte(0).lte(2)}); export const videoEyeContact = z.object({cameras: z.number().int().gte(0).lte(9007199254740991), camerasReady: z.number().int().gte(0).lte(9007199254740991), enabled: z.boolean(), status: z.enum(["off", "processing", "ready", "failed"])}); export const keystrokeSettings = z.object({alignment: z.enum(["left", "center", "right"]), animation: overlayAnimation, colors: z.object({background: z.string(), keyBackground: z.string(), keyText: z.string()}), displayDurationMs: z.number().int().gte(300).lte(10000), enabled: z.boolean(), filter: z.enum(["shortcuts", "all"]), labels: z.enum(["mac", "windows"]).optional(), position: z.object({x: z.number().gte(0).lte(1), y: z.number().gte(0).lte(1)}), size: z.number().gte(0.5).lte(4), style: z.enum(["keycap", "pill"]), typing: z.enum(["keys", "words"]).optional()}); export const videoSettingsLinkScope = z.enum(["public", "private", "org", "password", "embedonly"]); export const videoSettings = z.object({allowedEmbedDomains: z.array(z.string()), callToAction: videoCallToActionOutput.nullable(), callToActionsHidden: z.boolean(), captionFontFamily: captionFontFamily, captionFontSize: captionFontSize, captionFontWeight: captionFontWeight, captionGrouping: z.enum(["chunked", "singleWord"]), captionLinesPerBlock: captionLinesPerBlock, captionPosition: captionPosition.nullable(), captionSize: z.enum(["small", "medium", "large"]), captionStyle: captionStyle, captionsDefaultEnabled: z.boolean(), commentEmailsEnabled: z.boolean(), commentsEnabled: z.boolean(), creatorEnabled: z.boolean(), cursor: cursorSettings, customThumbnailURL: z.string().nullable(), defaultClipTransition: transitionStyle, defaultPlaybackRate: z.number().gte(0.5).lte(2), downloadsEnabled: z.boolean(), eyeContact: videoEyeContact.optional(), keystrokes: keystrokeSettings.optional(), layoutAnimationStyle: z.enum(["gentlest", "gentle", "relaxed", "smooth", "moderate", "brisk", "focused", "snappy", "punchy", "snappiest", "custom"]), linkScope: videoSettingsLinkScope, microphoneVolume: z.number().gte(0).lte(2), motionBlur: z.boolean(), motionBlurAmount: z.number().optional(), publishDateEnabled: z.boolean(), rawDownloadsEnabled: z.boolean(), searchEngineIndexingEnabled: z.boolean(), secondaryCallToAction: videoCallToActionOutput.nullable(), shrinkCameraDuringZooms: z.boolean(), studioSound: z.boolean(), studioSoundLevel: z.enum(["off", "low", "high"]), subtitlesEnabled: z.boolean(), systemAudioVolume: z.number().gte(0).lte(2), thumbnailInpointMs: z.number().int().gte(0).lte(9007199254740991).nullable(), transcriptsEnabled: z.boolean(), viewCountEnabled: z.boolean(), workspaceCallToAction: videoCallToActionOutput.nullable(), workspaceSecondaryCallToAction: videoCallToActionOutput.nullable(), zoomAnimationStyle: z.enum(["gentlest", "gentle", "relaxed", "smooth", "moderate", "brisk", "focused", "snappy", "punchy", "snappiest", "custom"])}); export const timelineVideoDetails = z.object({backgroundMusic: backgroundMusic.nullable().optional(), chapters: z.array(chapter).optional(), settings: videoSettings.optional()}); export const timelineDetails = z.object({clips: z.array(timelineClipDetails).optional(), video: timelineVideoDetails.optional()}); export const timelineVideo = z.object({aspectRatio: z.string(), description: z.string().max(5000), dimensions: z.object({height: z.number(), width: z.number()}), durationMs: z.number().gte(0), id: z.string(), name: z.string(), updatedAt: z.string()}); export const getTimelineResponse = z.object({clips: z.array(timelineClip), details: timelineDetails.optional(), included: z.array(z.enum(["settings", "chapters", "backgroundMusic", "clipSettings", "cuts", "layouts", "zooms", "blurs", "highlights", "overlays", "textOverlays", "soundEffects", "transcript", "words"])), video: timelineVideo}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Get a video's timeline * * GET /v1/videos/{id}/timeline */ export const getApiV1VideosIdTimeline = async (args: GetApiV1VideosIdTimelineArgs, options?: GetApiV1VideosIdTimelineOptions) => { const {baseUrl = "https://api.tella.com", fetch: fetchFn = fetch, BearerAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.clipIds != null) query.append("clipIds", String(args.clipIds)) if (args.include != null) query.append("include", String(args.include)) if (BearerAuth !== undefined) headers.set('authorization', `Bearer ${BearerAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/v1/videos/${encodeURIComponent(String(args.id))}/timeline${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(getTimelineResponse, await res.json()) };