Nimbryxo Studio

X Video Subtitle & Caption Transcript Converter

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.

Input schema

Input fields, types, required flags, descriptions, defaults, and prefills come from the published definition. Prefill examples are distinct from defaults.

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.
Show all input fields
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.

Download the published input schema

View complete JSON
{
  "properties": {
    "includeTweetMetadata": {
      "default": true,
      "description": "Attach the post's author, text and publish date to every transcript row.",
      "prefill": true,
      "title": "Include post details",
      "type": "boolean"
    },
    "includeWordTimestamps": {
      "default": false,
      "description": "Add 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.",
      "prefill": false,
      "title": "Include word timestamps",
      "type": "boolean"
    },
    "language": {
      "description": "Optional 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.",
      "editor": "textfield",
      "example": "en",
      "nullable": true,
      "title": "Spoken language hint (AI only)",
      "type": "string"
    },
    "outputFormat": {
      "default": "segments",
      "description": "Segments gives timestamped lines, full text gives one transcript string, and both gives you both in the same row.",
      "editor": "select",
      "enum": [
        "segments",
        "fullText",
        "both",
        "srt",
        "vtt"
      ],
      "enumTitles": [
        "Timestamped segments",
        "Full transcript text",
        "Both segments and full text",
        "SRT subtitle file text (downloadable)",
        "WebVTT subtitle file text (downloadable)"
      ],
      "prefill": "segments",
      "title": "Output format",
      "type": "string"
    },
    "postUrls": {
      "description": "One 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.",
      "editor": "stringList",
      "example": [
        "https://x.com/NASA/status/2107095768821576019",
        "https://twitter.com/elonmusk/status/1519480761749016577",
        "NASA"
      ],
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "prefill": [
        "https://x.com/NASA/status/2107095768821576019"
      ],
      "title": "Post links",
      "type": "array"
    },
    "profileUrls": {
      "description": "Optional. Transcribe the latest video post from these profiles. Paste x.com profile links or bare usernames.",
      "editor": "stringList",
      "example": [
        "NASA",
        "https://x.com/elonmusk"
      ],
      "items": {
        "type": "string"
      },
      "title": "Profile links or usernames",
      "type": "array"
    },
    "proxyConfiguration": {
      "description": "Optional. Use an Apify proxy if you plan large runs or see frequent rate limits.",
      "editor": "proxy",
      "sectionCaption": "Advanced",
      "sectionDescription": "Optional settings for large or repeated runs.",
      "title": "Proxy configuration",
      "type": "object"
    },
    "segmentGranularity": {
      "default": "segment",
      "description": "Level 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.",
      "editor": "select",
      "enum": [
        "segment",
        "sentence",
        "word"
      ],
      "enumTitles": [
        "Segment (raw caption/Whisper cues)",
        "Sentence",
        "Word (when per-word timings exist)"
      ],
      "prefill": "segment",
      "title": "Segment granularity",
      "type": "string"
    },
    "transcriptionMethod": {
      "default": "auto",
      "description": "Auto 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.",
      "editor": "select",
      "enum": [
        "auto",
        "captions",
        "ai"
      ],
      "enumTitles": [
        "Auto — built-in captions first, AI fallback",
        "Built-in captions only — skip videos without captions",
        "AI (Whisper) only — always transcribe the audio"
      ],
      "prefill": "auto",
      "title": "How to transcribe",
      "type": "string"
    },
    "whisperModel": {
      "default": "base",
      "description": "Whisper 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.",
      "editor": "select",
      "enum": [
        "tiny",
        "base",
        "small",
        "medium",
        "large-v2"
      ],
      "enumTitles": [
        "Tiny — fastest, lowest accuracy",
        "Base — fast and accurate (recommended)",
        "Small — more accurate, slower",
        "Medium — high accuracy, much slower",
        "Large-v2 — best accuracy, slowest"
      ],
      "prefill": "base",
      "title": "AI model size",
      "type": "string"
    }
  },
  "required": [
    "postUrls"
  ],
  "schemaVersion": 1,
  "title": "Twitter / X Video Transcript Scraper",
  "type": "object"
}

Output schema

Published result links and storage locations. This schema is not an exhaustive contract for every field in a dataset record.

FieldTypeRequiredDescription
transcriptsstringoptionalOne row per post, with transcript segments and/or the full transcript text.

Download the published output schema

View complete JSON
{
  "actorOutputSchemaVersion": 1,
  "description": "Per-post transcript records with timestamped segments, full transcript text, and optional SRT/VTT subtitle output.",
  "properties": {
    "transcripts": {
      "description": "One row per post, with transcript segments and/or the full transcript text.",
      "template": "{{links.apiDefaultDatasetUrl}}/items",
      "title": "Transcripts",
      "type": "string"
    }
  },
  "title": "X Video Subtitle & Caption Transcript Converter Output",
  "type": "object"
}

Dataset schema

Published dataset views and any declared field definitions. A view can select only a subset of the returned record fields.

Download the published dataset schema

View complete JSON
{
  "actorSpecification": 1,
  "views": {
    "segments": {
      "display": {
        "component": "table",
        "properties": {
          "authorUsername": {
            "label": "Author"
          },
          "end": {
            "format": "number",
            "label": "End (s)"
          },
          "index": {
            "format": "number",
            "label": "Segment #"
          },
          "language": {
            "label": "Language"
          },
          "start": {
            "format": "number",
            "label": "Start (s)"
          },
          "text": {
            "label": "Text"
          },
          "transcriptionMethod": {
            "label": "Method"
          },
          "tweetUrl": {
            "format": "link",
            "label": "Post URL"
          }
        }
      },
      "title": "Segments",
      "transformation": {
        "fields": [
          "tweetUrl",
          "authorUsername",
          "transcriptionMethod",
          "language",
          "index",
          "start",
          "end",
          "text"
        ],
        "unwind": [
          "segments"
        ]
      }
    },
    "transcripts": {
      "display": {
        "component": "table",
        "properties": {
          "authorName": {
            "label": "Author Name"
          },
          "authorUsername": {
            "label": "Author"
          },
          "collectedAt": {
            "format": "date",
            "label": "Data collected at"
          },
          "fullTranscript": {
            "label": "Full Transcript"
          },
          "language": {
            "label": "Language"
          },
          "modelUsed": {
            "label": "Whisper Model"
          },
          "publishedAt": {
            "label": "Published"
          },
          "transcriptAvailable": {
            "format": "boolean",
            "label": "Available"
          },
          "transcriptionMethod": {
            "label": "Method"
          },
          "tweetId": {
            "label": "Post ID"
          },
          "tweetUrl": {
            "format": "link",
            "label": "Post URL"
          },
          "type": {
            "label": "Row Type"
          }
        }
      },
      "title": "Transcripts",
      "transformation": {
        "fields": [
          "type",
          "tweetUrl",
          "tweetId",
          "authorUsername",
          "authorName",
          "language",
          "transcriptionMethod",
          "transcriptAvailable",
          "fullTranscript",
          "modelUsed",
          "publishedAt",
          "collectedAt"
        ]
      }
    }
  }
}

Key-value schema

Published key-value store definitions, when provided by this build.

This definition is not present in the default published build. See the published README for available documentation.

Published README

Read the full published documentation

X Video Subtitle & Caption Transcript Converter

Public X (Twitter) videos either already carry captions or need speech-to-text to become searchable text. This actor turns either case into a clean, timestamped transcript — reusing the video's own captions when they exist, and running AI speech-to-text when they don't — and can hand back ready-to-use SRT or WebVTT subtitle files, not just raw text. No login or cookies are needed.

What this actor does

  • Captions first: uses the video's own captions when the uploader or X provides them
  • Whisper AI fallback: automatically transcribes videos without captions, in any language
  • Three granularities: raw segments, sentences, or real per-word timings when available
  • Five output formats: timestamped segments, full text, both, SRT or WebVTT — with SRT/VTT files saved for download
  • Explicit outcomes: every post produces a row; posts with no transcript get transcriptAvailable: false and a clear message
  • Empty fields are omitted

Output per transcript

Each row has a type: video transcript when a transcript was produced, otherwise status.

Field Description
tweetUrl, tweetId Post URL and ID
authorUsername, authorName, authorFollowers Post author details (when Include post details is on)
tweetText, publishedAt Post text and publish time (when Include post details is on)
engagementRate Derived engagement in percent (when Include post details is on)
language Detected or requested language code
transcriptionMethod captions, ai or none
transcriptAvailable true when a transcript was produced
modelUsed Whisper model actually used for AI transcripts
modelNote Explanation when a smaller model was substituted for memory reasons
segmentGranularity segment, sentence or word — granularity actually applied
granularityRequested Present when the requested granularity could not be applied
granularityNote Explanation when a granularity fell back to raw segments
segmentCount Number of timed segments
segments [{index, start, end, text}]; includes real words[{word, start, end}] timings when available
fullTranscript Joined transcript text
srt, srtUrl SRT subtitle text and a signed download link for the .srt file
vtt, vttUrl WebVTT subtitle text and a signed download link for the .vtt file
message Explanation when no transcript could be produced
collectedAt UTC timestamp

Unavailable transcripts are status rows with transcriptAvailable: false, transcriptionMethod: "none" and a message explaining the reason. When the failure happens while resolving a profile input (instead of a post), the row carries profileUrl (and profileUsername, when known) instead of tweetUrl/tweetId.

Input

Field Type Default Description
postUrls array – Required. Post links (x.com or twitter.com) that contain a video or GIF. Profile links or usernames are accepted too — the actor transcribes the profile's latest video post
profileUrls array – Additional profiles to transcribe (latest video post each)
transcriptionMethod string auto auto (captions first, AI fallback), captions (skip videos without captions), ai (always Whisper)
whisperModel string base tiny, base, small, medium, large-v2
language string – Optional spoken-language hint for AI (e.g. en, es, ur); ignored for native captions
outputFormat string segments segments, fullText, both, srt, vtt
segmentGranularity string segment segment (raw cues), sentence, word (only when real word timings exist)
includeWordTimestamps boolean false Add real per-word start/end times to AI segments
includeTweetMetadata boolean true Attach author, post text and publish date to each row
proxyConfiguration object – Optional, for large or repeated runs

Example: captions first, AI fallback

{
  "postUrls": ["https://x.com/NASA/status/2107095768821576019"],
  "transcriptionMethod": "auto",
  "outputFormat": "both"
}

Example: always use AI with an English hint

{
  "postUrls": [
    "https://x.com/elonmusk/status/1519480761749016577",
    "NASA"
  ],
  "transcriptionMethod": "ai",
  "whisperModel": "small",
  "language": "en"
}

Example: SRT subtitle file

{
  "postUrls": ["https://x.com/NASA/status/2107095768821576019"],
  "outputFormat": "srt",
  "segmentGranularity": "sentence"
}

Example: word-level timestamps

{
  "postUrls": ["https://x.com/NASA/status/2107095768821576019"],
  "transcriptionMethod": "ai",
  "segmentGranularity": "word",
  "includeWordTimestamps": true
}

Example record

{
  "type": "video transcript",
  "tweetUrl": "https://x.com/NASA/status/2107095768821576019",
  "tweetId": "2107095768821576019",
  "authorUsername": "NASA",
  "authorName": "NASA",
  "language": "en",
  "transcriptionMethod": "ai",
  "transcriptAvailable": true,
  "modelUsed": "base",
  "segmentGranularity": "segment",
  "segmentCount": 1,
  "segments": [
    {
      "index": 0,
      "start": 0.0,
      "end": 11.0,
      "text": "One, booster ignition, and liftoff, the crew of Artemis II, now bound for the moon, humanity's next great voyage begins."
    }
  ],
  "fullTranscript": "One, booster ignition, and liftoff, the crew of Artemis II, now bound for the moon, humanity's next great voyage begins.",
  "publishedAt": "2026-10-05T13:09:13+00:00",
  "collectedAt": "2026-10-06T18:54:33+00:00"
}

Whisper models and memory

Model Speed Accuracy Recommended run memory
tiny Fastest Lowest 1024 MB
base Fast Good (default) 1024 MB
small Medium Better 2048 MB
medium Slow High 4096 MB
large-v2 Slowest Best 8192 MB

Long videos are split into 10-minute chunks automatically, so there is no video length limit. The actor runs with 8192 MB by default and never below 2048 MB. If the selected model does not fit the available memory, it automatically uses the next smaller model and records the substitution in modelNote instead of crashing. Caption-only runs have no meaningful memory requirement.

Use cases

  • Content accessibility — produce subtitles (SRT/VTT) for public videos
  • Media monitoring — transcribe interviews, press clips and announcements into searchable text
  • Research — build text corpora from public video content for analysis
  • Newsrooms — quote-check and index video statements quickly
  • Podcast and clip workflows — repurpose spoken content into articles or show notes
  • Social listening — combine transcripts with engagement data to track narratives

FAQ

Do I need an account or cookies? No. There is no cookie input; public posts, captions and media are read without login.

What happens when a video has no captions? With transcriptionMethod: auto (the default) the actor transcribes the audio with Whisper, so you still get a transcript. With captions it emits a row with transcriptAvailable: false and a message.

Can I transcribe multiple videos in one run? Yes — add links to postUrls, or point the actor at profiles and it transcribes the latest video post of each.

Which output format should I choose? segments for timestamped lines, fullText for one clean block of text, both for both, and srt/vtt when you need subtitle files (both the subtitle text and a signed download link are returned).

When does word-level granularity work? Word rows are emitted only when real per-word timings exist — Whisper can produce them, and some X captions include them. When they are missing, the row falls back to raw segments and explains why in granularityNote. Timings are never invented.

Can I transcribe videos in other languages? Yes — native captions work in any language X provides them; for AI, add a language hint (for example es, fr, ur) or leave it empty to detect automatically.

Does this support Twitter Spaces? No — this actor handles video and GIF posts only, not live audio Spaces.

Why is a row missing segments or fullTranscript? outputFormat controls which fields are filled, and unavailable transcripts never contain transcript fields — they are status rows with a message.

Can a deleted or protected post be transcribed? No, only videos on public, currently-live posts can be read.

Is this affiliated with X? No. This is an independent tool and is not affiliated with, endorsed by, or sponsored by X Corp.

Python quickstart

Use a schema-derived input and the Python standard library to start a run. An Apify account and token are required for execution.

Open the step-by-step Python guide →

Source build IeVVIA2c2aj2ljt2y. Documentation is regenerated from the default published build; private drafts are not included.