fp/services/factory/src/tasks/process_video.ts
CJ_Clippy 614bf16cf8
Some checks failed
ci / build (push) Failing after 1s
combine_video_segments progress
2024-09-03 08:28:39 -08:00

75 lines
2.7 KiB
TypeScript

import type { Helpers, Task } from "graphile-worker"
import { configs } from "../config"
import type { Stream } from '@futureporn/types'
import createVod from "../fetchers/createVod"
import getVod from "../fetchers/getVod"
interface Payload {
vod_id: string;
}
function assertPayload(payload: any): asserts payload is Payload {
if (typeof payload !== "object" || !payload) throw new Error("invalid payload (it must be an object)");
if (typeof payload.vod_id !== "string") throw new Error("payload.vod_id was not a string");
}
/**
*
* # process_video
*
* We just recorded a livestream. Now what?
* process_video takes a /vods record and runs a bunch of processes to get it ready for publishing.
*
* The following are graphile-worker tasks which process_video is responsible for adding to the job queue.
* Some of these tasks are run conditionally based on the structure of the /vods record.
* For example, combine_video_segments is only useful on a vod recording which ended up with multiple segments.
*
* - combine_video_segments
* - remux_video
* - generate_thumbnail
* - queue_moderator_review
* - create_mux_asset
* - create_torrent
*
* Some of the above Tasks are dependent on others. generate_thumbnail and everything following it depends on combine_video_segments.
* graphile-worker doesn't have support for dependent tasks,
* thus our solution is to invoke ALL the above jobs immediately, and build those jobs to fail if pre-conditions are unmet.
* all listed jobs are also idempotent, which means if they don't need to run (previously already performed their tasks), they will exit without doing anything.
*
*/
const process_video: Task = async function (payload: unknown, helpers: Helpers) {
assertPayload(payload)
const { vod_id } = payload
helpers.logger.info(`process_video task has begun for vod_id=${vod_id}`)
const vod = await getVod(vod_id, helpers)
if (!vod) throw new Error(`failed to get vod from database.`);
if (!vod.segments) throw new Error(`vod ${vod_id} fetched from database lacked any segments.`);
const isCombinationNeeded = (vod.segments.length > 1)
if (isCombinationNeeded) {
const s3_manifest = vod.segments.map((segment) => ({ key: segment.s3_key, bytes: segment.bytes }))
helpers.logger.info(`There are ${vod.segments.length} segments; Concatenation is needed.`)
helpers.addJob('combine_video_segments', { s3_manifest, vod_id })
} else {
helpers.addJob('remux_video', { vod_id })
}
helpers.addJob('generate_thumbnail', { vod_id })
// helpers.addJob('queue_moderator_review', { })
// helpers.addJob('create_mux_asset', { })
// helpers.addJob('create_torrent', { })
// helpers.addJob('create_ipfs', { })
}
export default process_video;