{"record":{"id":"5b223eb023f509ef","repo":"jackwener/OpenCLI","slug":"ext-mp4-mov-avi-webm","errorCode":null,"errorMessage":"不支持的视频格式: ${ext}（支持 mp4/mov/avi/webm）","messagePattern":"不支持的视频格式: (.+?)（支持 mp4/mov/avi/webm）","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/douyin/draft.js","lineNumber":313,"sourceCode":"    domain: 'creator.douyin.com',\n    strategy: Strategy.COOKIE,\n    navigateBefore: false,\n    args: [\n        { name: 'video', required: true, positional: true, help: '视频文件路径' },\n        { name: 'title', required: true, help: '视频标题（≤30字）' },\n        { name: 'caption', default: '', help: '正文内容（≤1000字，支持 #话题）' },\n        { name: 'cover', default: '', help: '封面图片路径' },\n        { name: 'visibility', default: 'public', choices: ['public', 'friends', 'private'] },\n    ],\n    columns: ['status', 'draft_id'],\n    func: async (page, kwargs) => {\n        const videoPath = path.resolve(kwargs.video);\n        if (!fs.existsSync(videoPath)) {\n            throw new ArgumentError(`视频文件不存在: ${videoPath}`);\n        }\n        const ext = path.extname(videoPath).toLowerCase();\n        if (!['.mp4', '.mov', '.avi', '.webm'].includes(ext)) {\n            throw new ArgumentError(`不支持的视频格式: ${ext}（支持 mp4/mov/avi/webm）`);\n        }\n        const title = kwargs.title;\n        if (title.length > 30) {\n            throw new ArgumentError('标题不能超过 30 字');\n        }\n        const caption = kwargs.caption || '';\n        if (caption.length > 1000) {\n            throw new ArgumentError('正文不能超过 1000 字');\n        }\n        const coverPath = kwargs.cover;\n        if (coverPath) {\n            if (!fs.existsSync(path.resolve(coverPath))) {\n                throw new ArgumentError(`封面文件不存在: ${path.resolve(coverPath)}`);\n            }\n        }\n        if (!page.setFileInput) {\n            throw new CommandExecutionError('当前浏览器适配器不支持文件注入', '请使用 Browser Bridge 或支持 setFileInput 的浏览器模式');\n        }","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/draft.js#L295-L331","documentation":"The douyin draft command validates the uploaded video's file extension against an allowlist (.mp4, .mov, .avi, .webm) before opening the upload page. If path.extname returns anything else, an ArgumentError is thrown naming the offending extension. This is a client-side guard so the browser automation never submits a file Douyin's uploader will reject.","triggerScenarios":"Calling `opencli douyin draft --video <file>` where the file exists but its extension (case-insensitive) is not .mp4/.mov/.avi/.webm — e.g. .mkv, .flv, .wmv, .m4v, .ts, or a file with no extension.","commonSituations":"Screen recordings saved as .mkv, GoPro/OBS footage in exotic codecs, renamed files without extensions, or passing a directory path that happens to resolve.","solutions":["Convert the video to MP4 (e.g. `ffmpeg -i input.mkv -c copy output.mp4`) and pass the new file","Rename the file with a supported extension ONLY if the actual container matches (renaming .mkv to .mp4 will fail at upload)","Check the extension: `node -e \"console.log(require('path').extname(process.argv[1]))\" yourfile` to confirm what the CLI sees"],"exampleFix":"// before\nawait cli.draft({ video: 'clip.mkv' });\n// after\n// convert first: ffmpeg -i clip.mkv clip.mp4\nawait cli.draft({ video: 'clip.mp4' });","handlingStrategy":"validation","validationCode":"const ok = ['.mp4', '.mov', '.avi', '.webm'].includes(path.extname(video).toLowerCase());\nif (!ok) throw new Error(`Convert ${video} to mp4/mov/avi/webm first`);","typeGuard":"const isSupportedVideo = (p) => ['.mp4', '.mov', '.avi', '.webm'].includes(require('path').extname(String(p)).toLowerCase());","tryCatchPattern":"try {\n  await cli.draft({ video, title });\n} catch (e) {\n  if (e instanceof ArgumentError && e.message.includes('不支持的视频格式')) {\n    console.error(`Re-encode with: ffmpeg -i ${video} ${video.replace(/\\.\\w+$/, '')}.mp4`);\n  } else throw e;\n}","preventionTips":["Standardize recording output to MP4 in OBS/editor settings","Run ffmpeg batch conversion as a pre-upload step in CI","Validate extensions in scripts before invoking the CLI"],"tags":["validation","file-format","argument-error"],"backgroundTag":"unsupported-file-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}