Shows with subtitles

If you already subtitle a show, you already have everything Signa needs: the words and when they are said.

The idea

  1. Read the subtitle file (SRT or VTT) into cues: a start time, an end time and the text.
  2. Sign each cue with /v1/sign.
  3. Turn each cue into a video with /v1/sign/video, and place it on a track at the cue's start time.

Signing usually runs a little longer or shorter than speech. Let a cue's signing run past its end time when the next cue starts later, and start the next one when it is due.

Example

Node.js
import { readFile, writeFile } from "node:fs/promises";

// Parse an SRT file into cues: { start, end, text } with times in seconds.
function parseSrt(srt) {
  const time = (t) => {
    const [h, m, s] = t.replace(",", ".").split(":");
    return +h * 3600 + +m * 60 + +s;
  };
  return srt.trim().split(/\r?\n\r?\n/).map((block) => {
    const lines = block.split(/\r?\n/);
    const [start, end] = lines[1].split(" --> ").map(time);
    return { start, end, text: lines.slice(2).join(" ") };
  });
}

async function sign(text) {
  const res = await fetch("https://api.usesigna.org/v1/sign", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SIGNA_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ text, from: "rw", to: "ksl" }),
  });
  if (!res.ok) throw new Error((await res.json()).message);
  return Buffer.from(await res.arrayBuffer());
}

const cues = parseSrt(await readFile("episode-12.srt", "utf8"));
for (const [i, cue] of cues.entries()) {
  const sgn = await sign(cue.text);
  // One signed file per cue, named by when it starts in the show.
  await writeFile(`signs/${String(i).padStart(4, "0")}-${cue.start.toFixed(2)}.sgn`, sgn);
}

Same words, same price

Shows repeat themselves: greetings, names, the weather. Words signed before are instant, and every cue is counted only by its own characters.