Nimbryxo Studio

Use X Video Subtitle & Caption Transcript Converter with Python

Convert public X (Twitter) videos into timestamped transcripts and downloadable SRT/VTT subtitle files, using native captions when available and AI speech-to-text otherwise.

1. Choose the data you need

Review the published README for supported collection modes, examples, and limits. The recipe below uses the current published input definition.

2. Prepare a source-based input

This JSON contains published prefills and required-field defaults. Review every value for your task before running it; it is not a promise of successful collection.

{
  "includeTweetMetadata": true,
  "includeWordTimestamps": false,
  "outputFormat": "segments",
  "postUrls": [
    "https://x.com/NASA/status/2107095768821576019"
  ],
  "segmentGranularity": "segment",
  "transcriptionMethod": "auto",
  "whisperModel": "base"
}

Download input.example.json and save your reviewed copy as input.json.

FieldTypeRequiredDescription
postUrlsarrayrequiredOne or more Twitter/X post links that contain a video or GIF. Both x.com and twitter.com links are accepted. Profile links or usernames also work: the actor transcribes the profile's latest video post.
profileUrlsarrayoptionalOptional. Transcribe the latest video post from these profiles. Paste x.com profile links or bare usernames.
transcriptionMethodstringoptionalAuto tries the video's built-in captions first and only falls back to Whisper AI when none exist. Captions-only skips videos without captions. AI-only always uses Whisper speech-to-text.
whisperModelstringoptionalWhisper model used for AI transcription. Larger models are more accurate but slower and need more memory (medium and large-v2 need a run memory of at least 4096 MB and 8192 MB respectively). Base is a good balance for most videos. If the selected model does not fit the run memory, the actor automatically falls back to the next smaller model. Long videos are split into 10-minute chunks automatically, so there is no length limit.
languagestringoptionalOptional language code for AI transcription, for example en, es, fr or ur. Improves accuracy when the spoken language is known. Leave empty to detect it automatically. Ignored when native captions are used.
outputFormatstringoptionalSegments gives timestamped lines, full text gives one transcript string, and both gives you both in the same row.
includeTweetMetadatabooleanoptionalAttach the post's author, text and publish date to every transcript row.
segmentGranularitystringoptionalLevel of the timestamped segments. Segment keeps the raw caption/Whisper cues. Sentence groups real word timings into sentences (or splits cue text, sharing the cue's real time range). Word emits one entry per real word timestamp and is used only when X captions or Whisper provide per-word timings — it is never fabricated; when word timings are missing, the row says so and keeps the raw segments.
includeWordTimestampsbooleanoptionalAdd per-word start/end times to AI (Whisper) transcript segments. Automatically enabled when Segment granularity is Sentence or Word. Native captions only carry words when X included inline timing markers.
proxyConfigurationobjectoptionalOptional. Use an Apify proxy if you plan large runs or see frequent rate limits.

3. Start an Actor run

Set APIFY_TOKEN in your environment. Python 3.10 or newer is sufficient; this recipe uses no third-party packages.

Execution may incur charges. Review current pricing on Apify. The request asks for a 120-second timeout and a charge limit; these settings are subject to Apify’s pricing and do not guarantee an all-inclusive spending cap.

import json
import os
import urllib.request

# Save the schema-derived example as input.json; review and edit it first.
with open("input.json", encoding="utf-8") as stream:
    actor_input = json.load(stream)

token = os.environ["APIFY_TOKEN"]
request = urllib.request.Request(
    "https://api.apify.com/v2/acts/SVs5jybOGSsqVgvbs/runs?timeout=120&maxTotalChargeUsd=0.50",
    data=json.dumps(actor_input).encode("utf-8"),
    headers={"Authorization": "Bearer " + token, "Content-Type": "application/json"},
    method="POST",
)
# This starts a potentially billable run. Do not automatically retry this POST.
with urllib.request.urlopen(request, timeout=40) as response:
    run = json.load(response)["data"]
print("Run ID:", run["id"])
print("Status:", run["status"])
# Inspect and download results in Apify Console once the run succeeds.

4. Inspect the actual results

Open the run in Apify Console and wait for a successful completion. Use the published output schema to locate results and the dataset schema to understand declared views. Missing or optional record fields must not be treated as guaranteed values.

Per-post transcript records with timestamped segments, full transcript text, and optional SRT/VTT subtitle output.

Questions before you run

Which inputs are required?

The published required fields are postUrls

What does this guide verify?

The fields, prefills, and schema links are rendered from the published build. This is a usage recipe, not a paid live extraction test. Source availability and collection results can vary.

What if the run request times out?

Check Apify Console before retrying. The first request may already have created a run. Do not automatically repeat a run-creation POST.

Generated from source build IeVVIA2c2aj2ljt2y and its README and schemas. Source changes regenerate this guide; no third-party editorial claims are inferred.