Shows with subtitles

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

No subtitles yet?

Make them from the programme itself with /v1/subtitles: send the file (or just its sound), get SRT or JSON cues back, check them, and carry on below.

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: "rsl" }),
  });
  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.