Input files
Anything placed in a project’sinput/ folder is an input file, however it got there: an API
upload, the AWS CLI, or an SDK. The processing service takes every file it finds, including files
in subfolders. In a project that reads a feed, the
input files are the feed items’ media, downloaded by the project itself and named from each item
(4f1c2b9a7d3e.8a2b4c6d.mp4); everything on this page applies to them as to uploaded files.
GET /projects/{id}/files lists them in name order, each with what it will produce:
meta counts every file by state. The same counts are kept on the project as files
(Projects), refreshed by this call, by
every change made through the API and once a minute otherwise, so a list of projects can be
polled instead of each project’s files. meta counts every file by state. ?status=failed (or several states, comma-separated) keeps
only those files in data, and GET /projects/{id}/files/{name} answers one file.
string
The file’s path under
input/. A file in a subfolder is season 2/episode 01.mp4.object[]
Every output the project’s config produces for this file, one per item of every destination: its
path under output/, whether it is available yet, and its size once it is. The files of an
output feed are under feeds/<language>/
(feeds/es/4f1c2b9a7d3e.8a2b4c6d.mp4).string | null
Set when
status is failed.string | null
Set when
status is failed: why, when it is something you can fix. no_audio (the file has
no audio track), not_media (not media, or truncated), voice_not_found (the config names a
voice the engine does not have), interrupted (processing was stopped before it finished;
retry), or internal (ours). See When a file
failed.boolean
true when the input was replaced after it was processed, by copying a new file over it with
the AWS CLI. The file reads pending, its outputs are still the old content’s, and nothing
happens until you retry it.object[] | null
What a
done file was billed for (Billing): one entry for its
captions in the transcription language, then a translation for each target language and a
dubbing for each dubbed one. Each entry has its kind, its language, and durationMs, the
file’s length that it is billed by. The file’s billed minutes are the sum of the entries’
durations.A retried file keeps the entries its content was first billed for, because a retry bills nothing
new; replaced content is billed again and has its own entries. usage is null while the file
is not done, and for up to a minute after it finishes, until it is recorded. durationMs is
null while processing has not reported the file’s length; the entry is billed once it has.States
A file whose input was replaced after it was processed is
pending with stale: true until you
retry it (Replace).
A file stays pending while its project is stopped. A project that stopped itself after its last
file starts again within a minute of a new file, however it was uploaded. Completing an API upload
also starts one stopped with POST …/stop; neither happens while the project’s startOnNewFiles
is off. Retrying a file starts a stopped project that ran before either way. Both answer the
project’s state in projectStatus; a project created with autoStart: false that never ran, or
one in error, is left as it is. See Starting again on a new file.
The processing service processes several files at a time, and takes the next file from the folder
as soon as one finishes, so a file uploaded while others are being processed starts as soon as
there is room for it.
A file that is being processed when its project stops (a stop, a change of config or
buildVersion, a restart) is left pending and processed again from the start when the project
next runs.
Subfolders
Subfolders ofinput/ are kept in output/: with a nameTemplate of ${name}.es.${ext},
input/season 2/episode 01.mp4 writes output/season 2/episode 01.es.mp4.
In a URL, a file’s name is one path segment, so encode its slashes along with everything
else: season%202%2Fepisode%2001.mp4. Every page that takes a {name} points here. Generated
clients do this for you (Generate a client); by hand:
Output names must not collide
Outputs are named from the input without its extension, sotrailer.mov and trailer.mkv
would both write trailer.es.mp4, and the second would overwrite the first. An API upload refuses
such a name with 422 (errors.name). A file copied in with the AWS CLI is not checked, so give
inputs distinct base names.
A name must not contain ${: output names are made by putting the input’s name into
${name}, and a ${ left over fails the file. An API upload refuses such a name.
Retry
202
done files too, for example after changing the
config. A retried file is not billed again unless its content changed.
A project that ran and has stopped since is started again. projectStatus says what the
project is doing now: stopped if it never ran (start it once every file is uploaded), error if
its last start failed.
Replace
Upload a file under the same name to replace adone one:
- Through the API, set
overwrite: trueon the upload (without it, a same-name upload answers409). The new file is processed from scratch. While the project is running, a file that is neitherdonenorfailedmay be mid-run, and replacing it answers409(file_processing). - With the AWS CLI, copy the new file over the old one, then retry it. Until the
retry, the file reads
pendingwithstale: true, and is not processed again.
Download
The download calls answer a presigned S3 URL, valid for up to an hour.
expiresAt is when it
stops working, which can be sooner than an hour; fetch a new one after that, rather than storing
it:
Authorization header. A browser saves the file
under its own name instead of playing it. With an upload
role, aws s3 sync <outputPath> ./results fetches everything at once.
Delete
DELETE /projects/{id}/files/{name} deletes an input file and its processing records. Its
outputs are kept; they stay listed by GET …/outputs.
While the project is running, a file that is neither done nor failed may be in the middle of
its run, which would finish and record the deleted file as done. Such a delete answers 409
(file_processing): wait for the file, or stop the project, then delete it.
Metadata
GET /projects/{id}/files/{name}/meta returns what the processing service recorded about the
file’s latest run, filled in as it goes: hash and startedAt when it starts, durationMs once
the media is read, dubbingMs after transcription, translation and dubbing, finishedAt when the
outputs are written.
404 (file_meta_not_found) until the run starts. A run before 2026-10-09 may carry
other fields.