75 lines
2.7 KiB
TypeScript
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;
|