A file can upload successfully and still be broken. The API returns 200, the asset shows ready, and the audio track never built.
Nobody notices until it airs, because the thing that checks files is usually a person, and people do not watch every asset end to end.
Automated video quality control is the fix, and it is two jobs rather than one. Check that the file is structurally sound, then check that the content is safe to air. This is how to do both against the FastPix API, and how to subtitle the file on the way through.
TL;DR
Automated video quality control starts with one call. GET /on-demand/{mediaId}/input-info returns the container format and every track in the file with its id, type and status, which tells you whether video and audio actually built. Use PATCH /on-demand/{mediaId}/moderation for the content check. A dedicated broadcast QC tool still measures loudness and artifacts, so store its verdict on the video as metadata. Subtitles come from an audio track, not the video: take the audio trackId out of the same input-info response and post it to the subtitle API.
What automated video quality control actually checks
Split this in two before writing anything, because the two halves fail differently.
| Check | Question it answers | Where it runs |
|---|---|---|
| Structural | Did the file build? Are the tracks there? | FastPix `input-info` |
| Compliance | Is loudness legal? Do captions drift? | A broadcast QC tool |
| Content | Is anything in here unsafe to air? | FastPix `moderation` |
| Runtime | Is the channel broken right now? | Channel monitoring |
The first and third are one API call each. The second needs a specialist. The fourth is a different system entirely, and confusing it with the first is the mistake that produces a channel failing live on a file that passed every ingest check.
How to check an uploaded file with the API
The video QC API is one call, and it gives you the whole structural picture:
import requests
from requests.auth import HTTPBasicAuth
BASE = "https://api.fastpix.com/v1"
AUTH = HTTPBasicAuth(ACCESS_TOKEN_ID, SECRET_KEY)
def probe(media_id):
r = requests.get(f"{BASE}/on-demand/{media_id}/input-info", auth=AUTH)
r.raise_for_status()
return r.json()["data"]["file"]The response gives you containerFormat and a tracks array. Each track carries an id, a type of video, audio or subtitle, and a status. Video tracks add width, height and frameRate.
That is enough for a real gate:
def structurally_ok(f, min_height=720):
tracks = f["tracks"]
video = [t for t in tracks if t["type"] == "video"]
audio = [t for t in tracks if t["type"] == "audio"]
if not video or not audio:
return False, "missing video or audio track"
if any(t["status"] != "available" for t in tracks):
return False, "a track did not finish processing"
if video[0]["height"] < min_height:
return False, f"source is {video[0]['height']}p"
return True, "ok"The missing-audio case is the one worth having. A silent programme is the failure people notice fastest and the one an ingest check catches most cheaply.
Running this against your own library is the fastest way to find out how many files would have failed. It works on a free account: Access Token ID and Secret Key come with $25 in credits and no card.
Where a broadcast QC tool goes further
Be clear about the boundary, because it decides how much broadcast QC automation you have to buy.
The FastPix probe tells you what landed. Tracks, status, resolution, container. It does not measure loudness against a broadcast standard, detect blockiness or dropped frames, check colour range, or verify that caption timing has not drifted from the audio.
Those are what Interra BATON, Telestream IQ and Witbe are built for, and if you are delivering to a platform with a technical spec, you will be asked for that report. The pattern is the same one you use everywhere else in this pipeline:
- The QC tool analyses the file.
- You write its pass or fail onto the video as metadata.
- Your scheduler reads that field before the video is eligible.
The tool does the judging. FastPix holds the judgment on the video, so nothing needs to stay in sync.
How to flag unsafe content automatically
Structural checks say nothing about what is in the frame. Moderation is a separate call, and it is the one that matters most as a gate:
requests.patch(f"{BASE}/on-demand/{media_id}/moderation",
auth=AUTH, json={"moderation": True})It runs as a job and fires a webhook when it finishes. Treat the result as a flag your code checks, not as an automatic block, because the borderline cases are exactly the ones a person should look at.
Content that is clearly unsafe should never reach a lineup. Content that is borderline should reach a review queue. Those are different outcomes and a single boolean will not give you both.
Both the probe and the moderation call are covered by the $25 in signup credits, so you can run the whole gate against a sample of real files before committing to a design.
How to generate subtitles with the API
Here is the part that surprises people: subtitles are generated from an audio track, not from the video. So you need a trackId before you can ask for them.
You already have it. The input-info call from the QC step returns every track with its id, which means one probe serves both halves of this pipeline:
def subtitle(media_id, language_code="en", language_name="English"):
f = probe(media_id)
audio = next(t for t in f["tracks"] if t["type"] == "audio")
r = requests.post(
f"{BASE}/on-demand/{media_id}/tracks/{audio['id']}/generate-subtitles",
auth=AUTH,
json={"languageCode": language_code,
"languageName": language_name,
"title": f"{language_name} subtitles"})
return r.json()["data"]["id"]The subtitle track is stored on the video itself rather than as a separate file you keep in sync, and video.media.subtitle.generated fires when it is ready. A video.media.updated event follows.
To add subtitles to a video from a dubbed audio track rather than the original, POST /on-demand/{mediaId}/tracks takes a url pointing at the audio file, plus type, languageCode and languageName. Then subtitle that track the same way.
One thing to keep straight: automatic subtitle generation is not part of FastPix In-Video AI. In-Video AI covers summaries, chapters, named entities and moderation. Subtitles sit under video management. Different feature, different call.
Why live subtitles need a different tool
This whole path runs on uploaded files. A live source gets none of it.
Real-time speech recognition has to run against the stream as it happens, which means a vendor like Ai-Media LEXI sitting alongside your encoder rather than a call against a stored asset. Plan the two paths separately from the start, because they share no code.
It is worth knowing where accuracy drops too. Speech recognition handles ordinary dialogue well and slips on names, places and specialist vocabulary, which in news and sport are the words carrying the meaning. That is also the programming regulators check most closely, so keep a person on live subtitle output even when the automated path is good.
How to gate a video before it airs
Put the pieces together and the gate is small:
Two habits worth building in. Log the reason, not just the result, because "failed QC" tells you nothing at 500 files a week. And make rejection loud. A file that silently fails a gate is the same outcome as a file that silently airs broken, just later.
The scheduler reads the output of this gate. That is covered in the AI channel scheduling guide.
Where to start
Run the probe across your existing library before building any of the gate. One loop over input-info for every asset, printing the failures, tells you whether you have a QC problem at all. Plenty of libraries come back clean, in which case build the moderation flag and skip the rest.
If the probe finds real failures, add rejection next and subtitles after. Subtitles feel like the visible feature and are the least likely thing to take a channel off air.
Both calls in this article run on a free account. Grab an API key with $25 in credits and point it at a few real files. When you want the channel behind it, book a demo.
Frequently Asked Questions (FAQs)
What is automated video quality control?
Automated video quality control is checking a video file with software instead of a person before it is published or aired. It covers two different jobs: confirming the file is structurally sound, meaning the video and audio tracks are valid, and confirming the content itself is safe to air.
How do you check video quality automatically?
Probe the file after upload and turn the result into a publishing gate. A single API call returns the container format and every track with its type and status, which is enough to reject a file with a missing audio track, an unavailable track, or a resolution below your required minimum. Log the reason for each rejection, not just the result.
What does the input-info endpoint return?
The input-info response returns the source URL, container format, and every track in the file with its ID, type, and status. Video tracks also include properties such as width, height, and frame rate. It does not measure loudness, detect visual artifacts, or validate caption timing.
Do I still need a broadcast QC tool?
For broadcast compliance, yes. The FastPix probe verifies whether the file is structurally sound, while dedicated QC tools can measure loudness against a standard, caption timing drift, blockiness, and color range. Store their pass or fail results as metadata on the video so your scheduler can use them.
How do I add subtitles to a video with an API?
Subtitles are generated from an audio track rather than directly from the video. Get the audio track ID from the input-info response, then send a POST request to /on-demand/{mediaId}/tracks/{trackId}/generate-subtitles with the languageCode and languageName. A video.media.subtitle.generated webhook fires when the subtitle track is ready.
What is the difference between subtitles and captions?
Subtitles provide spoken dialogue as text and generally assume the viewer can hear other audio. Captions also describe important sounds such as music, sound effects, and speaker changes, providing a fuller experience for deaf and hard-of-hearing viewers. Automatic speech recognition can produce subtitles, while complete captions may require additional contextual information.
Can you generate subtitles for a live stream?
Not through this workflow. Subtitle generation runs on uploaded video files. Live subtitling requires a real-time speech recognition service operating alongside the encoder and live streaming pipeline, so the live and on-demand workflows need to be handled separately.
How do you detect a video with no audio?
Read the tracks array returned by the file probe and verify that a track with type audio exists and has a status of available. A file can upload successfully and report as ready while still having no audio track, so this check can catch the problem before the video reaches viewers.
Which video formats can FastPix process?
FastPix can process common container formats including MP4, MOV, MKV, and TS, along with MP3 audio and SRT or VTT text tracks. The probe returns the container format of the uploaded file, allowing you to reject anything outside your accepted formats before it reaches a channel.





