Media processing
Extract video highlights and format them for social platforms.
Use a task to turn selected video moments into clips for TikTok, YouTube, and Instagram. Runlane manages the run, retry policy, and shared capacity. Your worker or media service performs the actual transforms.
Process one video for social platforms
Pass a video URL and a bounded list of timestamps. The Runlane calls below are real. The marked extractAndFormatSocialClips() call is pseudocode for FFmpeg, a cloud transcoder, or your own media pipeline:
import { queue, task } from '@runlane/core'
import * as z from 'zod'
const mediaQueue = queue({ name: 'media', concurrencyLimit: 2 })
const timestampSchema = z
.object({ end: z.number().nonnegative(), start: z.number().nonnegative() })
.refine(({ end, start }) => end > start, 'end must be greater than start')
const socialClipSchema = z.object({
platform: z.enum(['instagram', 'tiktok', 'youtube']),
url: z.url(),
})
const socialVideoSchema = z.object({ clips: z.array(socialClipSchema) })
export const processVideoForSocial = task({
id: 'media.process-for-social',
queue: mediaQueue,
schema: z.object({ timestamps: z.array(timestampSchema).max(20), videoUrl: z.url() }),
output: socialVideoSchema,
async run({ timestamps, videoUrl }, context) {
return context.step.run('process-social-clips', { output: socialVideoSchema }, async ({ token }) => {
//////////////////////////////////
// MAKE YOUR API CALLS HERE
//////////////////////////////////
const result = await extractAndFormatSocialClips({
idempotencyKey: token,
signal: context.signal,
timestamps,
videoUrl,
})
return socialVideoSchema.parse(result)
})
},
})The queue limits shared media capacity to two active attempts. The durable step stores the completed set of clips so a later attempt can reuse it. Pass its token to a remote service as an idempotency key when supported.
Keep video and clip bodies in object storage. Run payloads and outputs should contain stable object URLs or keys plus small metadata.
Local process or remote service?
| Option | Good fit | You must handle |
|---|---|---|
| Local process | The worker image already contains FFmpeg | Process timeout, cancellation, temp files, CPU and memory |
| Remote service | Jobs outlive one worker attempt | Submission idempotency, polling, credentials and result storage |
Always remove temporary files in finally. Pass context.signal to process or network wrappers. Prefer durable object keys when signed URLs may expire.
Before production
- Bound timestamp count, input size, runtime, temporary disk, and output size.
- Validate media type before processing.
- Test worker shutdown during processing.
- Make external submissions safe to repeat.
- Monitor provider failures separately from task failures.
For a provider that finishes later, use the release pattern in wait without failing.