Login and publish Douyin (China mainland) videos from local files with OAuth, local speech-to-text, and generated caption drafts. Use when users ask to autho...
--- name: douyin-upload-skill description: Login and publish Douyin (China mainland) videos from local files with OAuth, local speech-to-text, and generated caption drafts. Use when users ask to authorize Douyin accounts, upload local videos, auto-generate title/description from video audio, confirm content, and publish via official Douyin OpenAPI with fallback export when publish permissions are missing. --- # Douyin Upload Skill ## Overview Use this skill to publish local videos to Douyin with a deterministic CLI flow: 1. Validate local dependencies and env. 2. OAuth authorize and store encrypted token locally. 3. Prepare video metadata and transcript from local audio. 4. Generate 3 caption candidates in chat from transcript. 5. Confirm or edit caption, then publish. 6. If official publish permission is unavailable, export an outbox package for manual publish. Use the script at `<skill_root>/scripts/douyin.js`. ## Required Environment Set these environment variables before `auth` or `publish`: - `DOUYIN_CLIENT_KEY` - `DOUYIN_CLIENT_SECRET` - `DOUYIN_REDIRECT_URI` Optional overrides: - `DOUYIN_SCOPE` - `DOUYIN_TOKEN_ENC_KEY` - `DOUYIN_ASR_MODE` (`api` / `whisper-gpu` / `whisper-cpu`) - `DOUYIN_ASR_API_URL` - `DOUYIN_ASR_API_MODEL` - `DOUYIN_ASR_API_KEY` - `DOUYIN_WHISPER_BIN` - `DOUYIN_WHISPER_MODEL_PATH` - `DOUYIN_FFMPEG_BIN` - `DOUYIN_FFPROBE_BIN` ## Workflow 1. Run dependency checks: ```bash node <skill_root>/scripts/douyin.js doctor ``` 2. Authorize account (manual code paste flow): ```bash node <skill_root>/scripts/douyin.js auth ``` 3. Prepare transcript and metadata from a local video path. Accept both Linux and Windows path formats. ```bash node <skill_root>/scripts/douyin.js prepare --video "E:\\videos\\demo.mp4" ``` 4. Create 3 caption candidates from `transcript.text` with this structure: - Line 1: title hook - Line 2-3: concise description - Final line: 2-5 hashtags 5. Ask user to select or edit one final caption. 6. Publish with explicit visibility and confirmation policy: ```bash node <skill_root>/scripts/douyin.js publish \ --video "E:\\videos\\demo.mp4" \ --text "<final caption>" \ --private-status 0 \ --auto-confirm false ``` ## Command Behavior - `doctor`: reports dependency and env readiness plus install hints. - `auth`: opens OAuth URL, accepts pasted callback URL or `code`, stores encrypted token. - `prepare`: returns metadata, transcript, and ASR failure detail (without stopping publish flow). - `publish`: uploads and creates video via official API. If permission-like API errors occur, writes fallback files under outbox and returns `mode: fallback`. - `config`: stores persistent settings (`defaultPrivateStatus`, `autoConfirm`, `whisperBin`, `whisperModelPath`, `outboxDir`, etc.). ## Caption Rules Before publish: - Keep final text length <= 1000. - Always show the final draft to the user. - If `auto-confirm` is false, require explicit user confirmation in terminal. ## Output Contracts Treat script stdout as JSON. Always parse and branch by: - `ok` - `command` - `mode` (`official` or `fallback` for `publish`) - `asrError` (optional in `prepare`)
don't have the plugin yet? install it then click "run inline in claude" again.
by @clawhub
restructured into implexa's six-component format with explicit env var setup, decision branches for asr/token/permission failures, detailed output contract with json field specs, and edge cases for rate limits and network timeouts.
publish local videos to douyin (china mainland) with deterministic cli automation. use this when you need to authorize douyin accounts, upload local video files, auto-generate titles and descriptions from video audio, confirm captions in chat, and push to douyin's official api. fallback to offline outbox export if publish permissions are unavailable.
environment variables (required):
DOUYIN_CLIENT_KEY: oauth app client id from douyin open platformDOUYIN_CLIENT_SECRET: oauth app client secretDOUYIN_REDIRECT_URI: oauth callback url (must match douyin app settings exactly)environment variables (optional):
DOUYIN_SCOPE: oauth scope string (defaults to video.create)DOUYIN_TOKEN_ENC_KEY: encryption key for stored token (auto-generated if missing)DOUYIN_ASR_MODE: speech-to-text backend, one of api, whisper-gpu, whisper-cpu (defaults to whisper-cpu)DOUYIN_ASR_API_URL: remote asr endpoint url (only if mode is api)DOUYIN_ASR_API_MODEL: asr model name on remote (e.g. whisper-large)DOUYIN_ASR_API_KEY: api key for remote asr serviceDOUYIN_WHISPER_BIN: local whisper binary path (only if mode is whisper-gpu or whisper-cpu)DOUYIN_WHISPER_MODEL_PATH: local whisper model directoryDOUYIN_FFMPEG_BIN: ffmpeg binary path (defaults to system ffmpeg)DOUYIN_FFPROBE_BIN: ffprobe binary path (defaults to system ffprobe)external connections:
https://open.douyin.com/platform/oauth/connect (requires valid app credentials)video.create scope and active upload quotalocal file inputs:
/home/user/video.mp4 or E:\\videos\\demo.mp4)validate environment and dependencies
node <skill_root>/scripts/douyin.js doctorok (boolean), missingVars (array), missingBinaries (array), installHints (object)ok is false, stop and display install hints. if ffmpeg/ffprobe are missing, asr will fail later. if whisper binary is missing and mode is whisper-*, asr will fail.authorize douyin oauth account
DOUYIN_CLIENT_KEY, DOUYIN_CLIENT_SECRET, DOUYIN_REDIRECT_URI from envnode <skill_root>/scripts/douyin.js authok (boolean), authUrl (string), token (object with access_token, expires_in)~/.douyin/token.enc. if oauth fails (invalid creds, network timeout, or user denies), retry auth command. token expires in typically 2 hours; refresh token is not stored, so re-auth is required.extract video metadata and transcript
node <skill_root>/scripts/douyin.js prepare --video "<path>"ok (boolean), command ("prepare"), metadata (object with duration, resolution, fps, filesize), transcript (object with text (string), segments (array)), asrError (optional string if asr failed)asrError is present, log warning but continue to step 4 with empty transcript. if ok is false, stop and display error. accept both linux and windows paths; script normalizes internally.generate three caption candidates from transcript
transcript.text from step 3#vlog #travel #china)confirm final caption with user
publish video to douyin
node <skill_root>/scripts/douyin.js publish --video "<path>" --text "<caption>" --private-status 0 --auto-confirm falseok (boolean), command ("publish"), mode (string, either official or fallback), videoId (string if mode is official), outboxPath (string if mode is fallback)official, video has been uploaded to douyin api and assigned a videoId. if mode is fallback, api returned a permission-like error (e.g. quota exceeded, ip restricted, invalid scope); fallback files have been written to outbox directory for manual upload later. if ok is false, display error and do not attempt retry in this skill.DOUYIN_AUTO_CONFIRM=true is set in env.publish command will return error token_expired or similar. re-run auth command to refresh. do not store refresh tokens; they are not supported by douyin openapi.mode in output. if fallback, export files are ready. if ok is false, user lacks quota or scope. escalate to manual douyin studio upload.prepare command will fail in step 3 with ok: false. do not proceed to publish. ask user to verify file integrity with ffprobe before retry.api): prepare will return asrError but continue. if critical, user can set DOUYIN_ASR_MODE=whisper-cpu and retry step 3.ok: false with error field. wait 30 seconds and retry. if rate limit persists, douyin may be restricting your ip or quota; check douyin console.all commands output valid json to stdout. parse results by checking:
ok (boolean): true if command succeeded, false if error occurredcommand (string): name of command run (doctor, auth, prepare, publish)mode (string, publish only): official if api accepted upload, fallback if permission error triggered exportvideoId (string, publish with mode=official only): unique douyin video id for uploaded contentoutboxPath (string, publish with mode=fallback only): directory path containing exported caption and metadata jsonasrError (string, prepare only): error message if speech-to-text failed; presence does not block outputtoken (object, auth only): {access_token, expires_in, refresh_token (may be null)}metadata (object, prepare only): {duration (seconds), resolution (string, e.g. "1920x1080"), fps (number), filesize (bytes)}transcript (object, prepare only): {text (string), segments (array of {start, end, text})}error (string, any command): human-readable error message if ok is falsefile locations:
~/.douyin/token.enc~/.douyin/outbox/<timestamp>/ (contains caption.json, metadata.json)~/.douyin/config.jsonok: true, token.access_token is non-empty, token file is created at ~/.douyin/token.encok: true, transcript.text contains extracted speech (or is empty if asr failed), metadata fields are populatedok: true, mode: "official", videoId is a non-empty string. video appears in douyin creator dashboard within 1-5 minutes (pending content review).ok: true, mode: "fallback", outboxPath points to a directory with json files ready for manual uploadok: false, error field explains reason (e.g. "token_expired", "video_too_short", "invalid_credentials"). no files are written or modified.