# Video Transcript & Summary — YouTube, TikTok, Instagram, X (`almoutasem_nabil/video-transcript-summary`) Actor

Transcripts with timestamps for YouTube, TikTok, Instagram Reels and X videos, from captions or speech recognition. Arabic dialects and English, optional translation and AI summary with chapters and keywords.

- **URL**: https://apify.com/almoutasem\_nabil/video-transcript-summary.md
- **Developed by:** [Al Moutasem Nabil](https://apify.com/almoutasem_nabil) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 transcript (captions)s

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Video Transcript & Summary — YouTube, TikTok, Instagram, X

Transcripts with timestamps for YouTube, TikTok, Instagram Reels and X videos, from captions or
speech recognition. Arabic dialects and English, optional translation and AI summary with chapters
and keywords.

تفريغ الفيديو وترجمة وملخص — يوتيوب، تيك توك، إنستغرام، إكس. يدعم اللهجات الخليجية والشامية والمصرية،
والملخص يُكتب بالعربية الفصحى مع الحفاظ على اللهجة كما نُطقت في النص الأصلي.

### Who it's for

- **Content teams** repurposing long videos into clips, posts and newsletters.
- **Researchers and analysts** who need searchable text from many videos at once.
- **Marketers** studying hooks and calls to action across competitors' short-form video.
- **AI agents and automations** that need a transcript as a synchronous API call (see Standby below).

### What makes it different

- **Four platforms in one schema.** YouTube, TikTok, Instagram Reels and X return the same fields.
- **Captions first, speech recognition second.** When a platform already publishes captions the
  Actor uses them: exact, already timed, and far cheaper than transcribing audio.
- **Arabic as a first-class language.** Dialect is preserved verbatim in the transcript; summaries
  are written in Modern Standard Arabic. Keyword extraction normalizes alef, yaa, taa marbuta and
  tashkeel so "أحمد" and "احمد" count as one word.
- **Clean sentences, not caption fragments.** Auto-captions arrive as an overlapping rolling window
  ("so today", "so today we're", "so today we're building"); the Actor merges them back into
  sentences while keeping the start time of the first fragment, so timestamps stay accurate.
- **Nothing is stored or rehosted.** Audio is extracted at 16 kHz mono only for transcription and
  deleted immediately, on failures too. The output is text.

### Input

```json
{
    "videoUrls": [
        "https://www.youtube.com/watch?v=aircAruvnKk",
        "https://www.tiktok.com/@user/video/7137723462233444614"
    ],
    "language": "auto",
    "includeTimestamps": true,
    "translateTo": "ar",
    "summarize": true,
    "maxDurationMinutes": 60,
    "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

YouTube channel and playlist URLs are expanded to their most recent videos (`maxVideosPerSource`).

### Output

One dataset item per video. Every field is documented in `.actor/dataset_schema.json`, and the
Console shows three views: **Transcripts**, **Summaries** and **Errors**.

```json
{
    "platform": "youtube",
    "videoId": "aircAruvnKk",
    "url": "https://www.youtube.com/watch?v=aircAruvnKk",
    "title": "But what is a neural network?",
    "author": "3Blue1Brown",
    "publishedAt": "2017-10-05T00:00:00.000Z",
    "durationSec": 1134,
    "language": "en",
    "transcriptSource": "captions",
    "asrProvider": null,
    "segments": [{ "startSec": 12.4, "endSec": 15.8, "text": "This is a 3, and it's sloppily written." }],
    "text": "This is a 3, and it's sloppily written.\nBut it's still recognisable.",
    "wordCount": 1842,
    "translation": null,
    "summary": null,
    "processingMs": 4210,
    "scrapedAt": "2026-09-07T01:20:00.000Z"
}
```

`transcriptSource` tells you what you paid for: `captions` and `auto-captions` are the cheap path,
`asr` means the audio was transcribed per minute.

Videos that produce no transcript are stored as error items with the failing `stage` — and are
**never charged**.

### Pricing

Pay-per-event. You pay for finished work, never for a video the Actor could not read.

| Event                                  | Price  | When                                                    |
| -------------------------------------- | ------ | ------------------------------------------------------- |
| Video processed                        | $0.002 | Per video whose metadata was fetched.                   |
| Transcript from captions               | $0.005 | Per video transcribed from the platform's own captions. |
| Transcript minute (speech recognition) | $0.005 | Per audio minute, rounded up, only after it succeeds.   |
| Translation                            | $0.01  | Per video translated.                                   |
| AI summary                             | $0.02  | Per video summarized.                                   |

Worked examples:

- **100 YouTube videos that have captions**: 100 × $0.002 + 100 × $0.005 = **$0.70**.
- **One 10-minute TikTok without captions, plus a summary**: $0.002 + 10 × $0.005 + $0.02 = **$0.072**.

Apify's own `apify-actor-start` fee and platform compute are billed separately by your plan. Default
memory is 1024 MB, which is enough for every path including audio extraction.

### Scheduling and integrations

1. Fill in the input and **Save as task**.
2. Add a **Schedule** to the task for a recurring pull.
3. Under **Integrations**, send results to Slack, Google Sheets, a webhook, Make or Zapier on
   *Run succeeded*.
4. From n8n or Make, call the Apify node with this Actor and read the dataset, or use Standby below
   for a synchronous single-video call.

### Use as an API / MCP tool

With **Standby** enabled the Actor stays warm and answers one video per HTTP request, which is what
an AI agent wants instead of starting a run and polling:

```
GET https://<your-actor>.apify.actor/?url=https://youtu.be/aircAruvnKk&summarize=1&translateTo=ar
```

Query parameters mirror the input fields (`url`, `language`, `translateTo`, `summarize`,
`summaryLanguage`, `includeTimestamps`, `forceAsr`, `maxDurationMinutes`). The response is JSON with
`items` and `errors`. `GET /health` returns `{"ok":true}`.

### Limitations, honestly

- **YouTube requires residential proxies.** From datacenter IPs YouTube answers
  "Sign in to confirm you're not a bot" and serves neither captions nor audio. Set
  `proxyConfiguration` to `{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}`. Even then
  YouTube's bot checks vary by IP and by video; the caption path is the part most likely to need a
  yt-dlp bump (see `Dockerfile`, `YT_DLP_VERSION`).
- **Instagram and X are off by default** (`enableInstagram`, `enableX`). Neither publishes captions,
  so every video costs speech recognition, and both block datacenter traffic aggressively.
- **Speech recognition needs a provider key** set on the Actor (`GROQ_API_KEY`, `DEEPGRAM_API_KEY`
  or `OPENAI_API_KEY`). Without one, videos that have no captions produce an error item rather than
  a transcript. Summaries and non-YouTube translation need `OPENROUTER_API_KEY` or `OPENAI_API_KEY`.
- **`maxDurationMinutes` is the cost control.** Longer videos are skipped with an error item instead
  of running up a per-minute bill.
- **Heavy dialect reduces accuracy.** Naming the language (`"ar"`) instead of `auto` measurably
  helps; auto-captions on dialect-heavy content are often worse than `forceAsr`.
- **Live streams are rejected** — there is no finished transcript to return.

### Legal note

The Actor reads publicly available videos and their published captions. It never logs in and sends
no cookies. Audio is downloaded only as a temporary intermediate for transcription and deleted
immediately; no media is stored or rehosted, and the output is text. Only public channel names and
handles are recorded — no viewer names, no comments, no personal contact details. Use the output in
line with each platform's terms and the copyright that applies to the source video. YouTube, TikTok,
Instagram and X are trademarks of their owners; this Actor is not affiliated with them.

# Actor input Schema

## `videoUrls` (type: `array`):

Video links to transcribe. YouTube channel and playlist URLs are expanded to their most recent videos (see 'Max videos per channel'). Supported: youtube.com/watch, youtu.be, YouTube Shorts, tiktok.com, instagram.com and x.com video links.

## `maxVideosPerSource` (type: `integer`):

How many recent videos to take from each channel or playlist URL. Ignored for links to a single video.

## `language` (type: `string`):

Hint for speech recognition and for choosing among caption tracks. 'auto' detects the language, but naming it ('ar' or 'en') noticeably improves accuracy on Arabic dialects.

## `includeTimestamps` (type: `boolean`):

Return the timed 'segments' array alongside the plain transcript. Turn off for smaller items when you only want the text.

## `translateTo` (type: `string`):

ISO code of a language to translate the transcript into, for example 'en' or 'ar'. Leave empty for no translation. On YouTube this uses the platform's own caption translation, so it is fast and adds no speech-recognition cost.

## `summarize` (type: `boolean`):

Add a one-line summary, bullet points, chapters with timestamps, keywords, the hook and the call to action. Arabic summaries are written in Modern Standard Arabic while the transcript keeps the dialect as spoken.

## `summaryLanguage` (type: `string`):

ISO code for the summary language. Leave empty to summarize in the language of the transcript.

## `maxDurationMinutes` (type: `integer`):

Videos longer than this are skipped and reported as an error item rather than transcribed. This is the main control on cost, because speech recognition is billed per minute.

## `forceAsr` (type: `boolean`):

Ignore published captions and transcribe the audio instead. Slower and billed per minute, but worth it when a platform's auto-captions mis-hear heavy dialect.

## `enableInstagram` (type: `boolean`):

Instagram publishes no captions, so every Reel costs speech recognition, and Instagram blocks datacenter traffic often. Off by default; turn on together with residential proxies.

## `enableX` (type: `boolean`):

X publishes no captions, so every video costs speech recognition, and access is unreliable without residential proxies. Off by default.

## `maxConcurrency` (type: `integer`):

How many videos are processed in parallel. Lower this if a platform starts rate-limiting you.

## `proxyConfiguration` (type: `object`):

Proxies for the requests. Apify datacenter proxies are enough for YouTube and TikTok; switch to residential for Instagram and X.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=aircAruvnKk",
    "https://www.youtube.com/watch?v=Unzc731iCUY"
  ],
  "maxVideosPerSource": 20,
  "language": "auto",
  "includeTimestamps": true,
  "summarize": false,
  "maxDurationMinutes": 60,
  "forceAsr": false,
  "enableInstagram": false,
  "enableX": false,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

One item per video: metadata, the transcript with timestamps, and the optional translation and AI summary. Videos that produced no transcript appear as error items and are never charged.

## `summary` (type: `string`):

Videos requested and processed, transcripts stored, speech-recognition providers configured and the charged-event tally.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "videoUrls": [
        "https://www.youtube.com/watch?v=aircAruvnKk",
        "https://www.youtube.com/watch?v=Unzc731iCUY"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("almoutasem_nabil/video-transcript-summary").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "videoUrls": [
        "https://www.youtube.com/watch?v=aircAruvnKk",
        "https://www.youtube.com/watch?v=Unzc731iCUY",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("almoutasem_nabil/video-transcript-summary").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "videoUrls": [
    "https://www.youtube.com/watch?v=aircAruvnKk",
    "https://www.youtube.com/watch?v=Unzc731iCUY"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call almoutasem_nabil/video-transcript-summary --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,almoutasem_nabil/video-transcript-summary"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/FZYI4cIhvaL1gPWnl/builds/xzo1WROSUORIAgs1O/openapi.json
