# videosays

AI-agent-friendly CLI for video transcription, video to text, speech to text, subtitle extraction, and transcript export.

Videosays turns supported video links or share text into clean transcript text, timestamped timelines, SRT subtitles, and VTT subtitles.

中文：Videosays 是面向 AI Agent 和命令行用户的视频文案提取 CLI，支持抖音文案提取、小红书视频转文字等，可把公开视频链接或分享文本转成纯文本、带时间轴文本、SRT 字幕和 VTT 字幕。

Supported platforms include Douyin, TikTok, Xiaohongshu, Bilibili, YouTube, and Kuaishou. Availability can vary by source video accessibility, region, platform restrictions, and whether captions or transcribable audio are available.

支持平台包括抖音、TikTok、小红书、Bilibili、YouTube、快手。实际可用性会受视频访问权限、地区、平台限制、字幕或音频可获取性影响。

## Install

```bash
# Use directly
npx videosays login

# Or install globally
npm install -g videosays
videosays login
```

Requires Node.js >= 18.

## Quick Start

```bash
# First use: authorize in the browser, then save API key to ~/.videosays
videosays login

# Transcribe a video link or share text
videosays transcribe "https://www.tiktok.com/@creator/video/123456"

# Retrieve the result after the returned Task ID is ready
videosays status "<task-id>"
```

## Commands

```bash
videosays login
videosays login --api-key <api-key>
videosays logout
videosays whoami
videosays transcribe <video-link-or-share-text>
videosays transcribe <video-link-or-share-text> --force-new
videosays transcribe <video-link-or-share-text> --submission-id <uuid>
videosays transcribe <video-link-or-share-text> --format text
videosays transcribe <video-link-or-share-text> --format timeline
videosays transcribe <video-link-or-share-text> --format srt
videosays transcribe <video-link-or-share-text> --format vtt
videosays status <taskId>
videosays status <taskId> --format srt
videosays batch <links.txt>
videosays batch <links.txt> --force-new
videosays batch <links.txt> --submission-id <uuid>
videosays batch status <batch-id>
videosays batch continue <batch-id>
videosays batch cancel <batch-id>
videosays balance
videosays history [limit]
videosays doctor
videosays help
```

Submission commands return promptly with a server Task ID or Batch ID. Each command sends a client-generated `Idempotency-Key`; repeat an ambiguous request with the same `--submission-id <uuid>` to receive the original resource safely. Equivalent active work for the same account is reused, and completed work is reused by default. Use `--force-new` for an intentional fresh transcription. Capture the returned ID and use `status` or `batch status` as short, one-shot checks; never rerun a submission command to check progress. Add `--wait` only for an interactive terminal that should remain attached.

Batch status checks use a lightweight response while work is running and retrieve complete Task results once after the batch finishes. If the batch pauses for insufficient credits, completed Tasks remain intact; top up and run `batch continue <batch-id>` to resume the remaining Tasks under the same Batch ID.

For multiple links, put one input per line in a text file and use `batch`. Duplicate lines are preserved as separate Tasks. The server processes Tasks through its bounded queue and reserves credit atomically. If credit is insufficient, unstarted Tasks are skipped; top up and run `batch continue <batch-id>`.

## Transcription Output

By default, `transcribe` submits and immediately prints a pending receipt. `status` prints transcript text after completion. Both commands use text output unless another format is requested.

Use `--format` when the user asks for a different result shape:

```bash
videosays transcribe "<video-link>" --format text
videosays status "<task-id>" --format timeline
videosays status "<task-id>" --format srt
videosays status "<task-id>" --format vtt
```

Formats:

- `text`: plain transcript, default
- `timeline`: timestamped transcript segments
- `srt`: SRT subtitle file content
- `vtt`: VTT subtitle file content

输出格式：

- `text`: 纯文本，默认格式
- `timeline`: 带时间轴分段
- `srt`: SRT 字幕
- `vtt`: VTT 字幕

If a task is still running, the command prints a pending block:

```text
VIDEOSAYS_TASK_PENDING
task_id=<task-id>
status=processing
next=videosays status <task-id>
```

Run the `next` command later until transcript text or the requested format is returned.

Errors are printed to stderr and exit non-zero:

```text
Error: 余额不足，请充值后再提交任务。
Code: insufficient_credits
Next: videosays balance
Recharge: https://videosays.cn/dashboard/billing
```

## Configuration

The API key is saved to `~/.videosays` by default. The default API and official login/recharge pages use `.cn`; the same account and credits are available through both domains. Existing installations must update to receive this change. For this tested release, use `npm install -g videosays@1.3.0` or `npx videosays@1.3.0`. Published Skill commands pin the same version.

默认使用 `api.videosays.cn`，登录和充值页面也使用 `.cn`。账号和分钟数不变。已经安装过的 CLI 需要更新；临时设置 API 环境变量只能修改 API 请求，旧版 CLI 的登录和充值链接仍可能指向 `.com`。

Environment variables:

```bash
export VIDEOSAYS_API_KEY="vs_xxxxx"
export VIDEOSAYS_API_URL="https://api.videosays.cn"
```

The CLI prefers HTTP/2 for HTTPS requests and rotates through resolved IPv4/IPv6 addresses when a safe request fails at the network layer. Read-only requests are retried, and a transcription or batch submission is retried only with its original `Idempotency-Key`. An explicit HTTP response from a submission is never retried automatically. Use `videosays doctor` to probe each resolved API address without an API key. `VIDEOSAYS_DISABLE_HTTP2=1` is available as a troubleshooting override.

An explicit `VIDEOSAYS_API_URL` still takes precedence. For the global endpoint:

```bash
export VIDEOSAYS_API_URL="https://api.videosays.com"
```

The CLI never switches endpoints or retries a submission against a second domain. Interface language and API origin are separate choices.

## License

MIT
