ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AI生图+FFmpeg:自制前奏MV的完整制作流程

AI生图+FFmpeg:自制前奏MV的完整制作流程 给一首歌曲的前奏配一支用 AI 生图做出来的自制 MV不需要实拍、不需要演员和复杂设备但依然要经历一条比较完整的制作链路先拆解前奏的声音结构再把每一段听感翻译成画面卡片接着用 AI 生图工具批量渲染静态帧最后把静态帧合成视频并与音轨对齐。这个过程很适合作为练习项目因为它把“画面审美”和“工程参数”揉在一起既能练提示词也能练 FFmpeg 处理音视频的基本功。这篇文章不打算只讲“如何让 AI 画一张图”而是用“自制 MVAI 生图”作为目标把一套可以复用的制作流程拆开讲清楚。我会按实际做项目时会遇到的顺序组织内容先搭建贯穿始终的时间轴和分镜表再准备本地 AI 生图环境和批量脚本然后解决画面不一致、皮肤质感塑料等问题最后用 FFmpeg 完成剪辑、拼接和音画同步。每部分都尽量包含可执行命令、可改参数和常见坑。示例音频和歌词内容不展开重点是把流程跑通。1. 先给前奏建一条时间轴而不是急着批量生图1.1 静态图和视频的本质差别是时间AI 生图生成的是静态画面MV 是随时间变化的视频。很多人直接从“让 AI 画 100 张图”开始结果最后拼出来的视频像幻灯片画面和音乐各走各的。问题不一定是图质量差而是没有时间轴。视频的基本单位是帧。无论每张图多好看放进时间轴后观众看到的是顺序、时长、运动方式和声音之间的关系。一段前奏可能只有几十秒但它内部并不均匀开头可能是环境声或低音铺底中间会进入吉他或键盘可能还有小号、鼓点或人声进入。每段声音给观众的想象方向不同对应的画面也应该不同。所以制作前要先把前奏当成一条完整音轨来听找出几个明显变化点。比如某段鼓进入、某段旋律转折、某个乐器停止这些点就是画面的切换依据。通常不需要精确到帧但至少要把段落切到秒级。1.2 给前奏建立听觉分镜表分镜表不是导演专利普通人做视觉创作也应该先写。分镜表只需要记录四个信息时间范围、声音特征、画面内容、画面运动方式。下面是一张通用示例表实际制作时应根据你的音轨和歌曲结构调整段落时间示例听到什么画面想法构图建议0100:00 - 00:08低频铺底、环境噪声夜晚旧城区远景、雨雾、昏黄路灯远景地平线靠下留出大量天空0200:08 - 00:20吉他或键盘开始进入慢慢推近一栋老居民楼窗户微亮中远景主体居中偏右0300:20 - 00:35管乐或人声准备进入室内近景桌上一把小号或乐器特写浅景深0400:35 - 之后节奏变强或段落收束人物剪影站在窗前窗外城市灯光全景剪影这里有两个要点。第一不要把每个画面写得太满AI 生图本身会补充大量细节分镜只控制叙事方向。第二要同时写“构图建议”因为后面生成图片时宽高比和主体位置会影响 FFmpeg 推拉镜头时的观感。如果主体太靠画面边缘推镜头时容易裁掉关键内容。1.3 把听觉意象写成可生成画面卡片分镜表定下来后每个场景要扩展成一张“画面卡片”。这张卡片可以放在 JSON 里也可以写进文本文件。格式不重要但字段必须完整镜头编号、时间长度、画面描述、提示词词根、负面提示词、种子、宽高比。例如一个“雨夜旧厂房”画面卡片可以是{ id: 1, duration_sec: 8, audio_note: 低频铺底, vision: 雨夜旧工业区远景街灯朦胧路面反光, prompt_base: film still, rain night, old industrial area, dim street lamps, reflective wet road, cinematic composition, muted blue and orange, film grain, negative_prompt: text, watermark, frame, border, cartoon, painting, deformed, oversaturated, plastic skin, seed: 10001, width: 1024, height: 576 }“prompt_base”不一定是一次成稿的最终提示词但它给出了场景的稳定基础。后面不管你写的是人像近景还是城市全景都可以在这个基础上做替换。这样做的价值是当生成结果不满意时你只需要改局部关键词不需要重写整套提示词。如果你给某支乐队做“杀石前奏”相关画面情绪上偏向旧工业、城市日常、夜晚灯光这一步尤其重要。旧工业城市意象很容易被画成重复的空镜头只有把时间点和声音特征对应起来画面才不会完全脱离音乐。2. 搭建本地 AI 生图环境并用脚本批量出帧2.1 本地生图需要哪些运行条件这一步的目的是建立可重复的批量生成能力而不是只在线网页里生成一两次。自制 MV 通常需要几十张图反复调整后可能要生成几百张如果一张一张手动点击保存效率太低。这时本地生图工具加脚本会更适合。本地生成需要一块显存足够的 GPU。常见情况下显存 6GB 到 8GB 可以跑一些轻量模型显存 12GB 以上会更从容。不同模型参数量和分辨率要求不同原始素材没有给出明确版本配置前要先确认自己使用的工具版本、模型文件和 Python 版本是否匹配。学习环境下可以降低分辨率比如先用 768x432 出草稿确认镜头和构图后再出 1024x576 的正式帧。推荐的目录结构ai-mv/ ├── frames/ # 渲染出来的原始帧 ├── clips/ # 单镜头视频片段 ├── json/ # 分镜和场景参数 ├── scripts/ # Python 批处理脚本 ├── audio/ # 有合法使用权的音轨 └── output/ # 最终视频把原始帧、过程片段和最终文件分开后续清理非常方便。不要把所有素材堆在同一目录否则很容易把中间帧覆盖或混进拼接列表。2.2 启动带 API 的生图服务以本地 Stable Diffusion WebUI 一类工具为例手动启动时通常只需要在命令行里加上--api让脚本可以调用 HTTP 接口。这里不绑定某个固定框架只要你的生图服务暴露了类似 txt2img 的 API后面的流程可以平移。先创建虚拟环境并启动服务cd ~/ai-mv python3 -m venv venv source venv/bin/activate git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git cd stable-diffusion-webui pip install -r requirements.txt ./webui.sh --api不同系统的启动脚本不一样。Windows 上通常是webui-user.batLinux 或 macOS 上是webui.sh。--api参数是给本地脚本用的先打开这个开关后面才能通过请求批量生成。启动完成后用下面命令确认 API 是否正常curl http://127.0.0.1:7860/sdapi/v1/options能返回一段 JSON 就说明服务已经起来。这里要注意不要在公网环境中把服务地址暴露出去。如果需要从其他设备调用可以加--listen但要配合防火墙和访问控制普通学习环境保持127.0.0.1就足够。2.3 用 scenes.json 管理每一个镜头的参数把每个镜头的参数集中到一个 JSON 文件里脚本读 JSON批量提交给生图 API。用文件而不是硬编码的好处是参数可视化方便对比不同种子的效果也能保留历史。一个简化的 scenes.json{ scenes: [ { id: 1, duration_sec: 8, prompt: film still, rain night, old industrial area, dim street lamps, reflective wet road, cinematic composition, muted blue and orange, film grain, negative_prompt: text, watermark, deformed, film frame, cartoon, plastic skin, seed: 10001, width: 1024, height: 576, steps: 30, cfg_scale: 7 }, { id: 2, duration_sec: 10, prompt: film still, 1980s concrete urban residential buildings at night, one window lit, subtle rain, cinematic close-up, film grain, negative_prompt: text, watermark, deformed, film frame, cartoon, plastic skin, seed: 10002, width: 1024, height: 576, steps: 30, cfg_scale: 7 } ] }每个镜头都建议记录固定 seed。seed 是随机数种子固定它能复现同一张图的效果。生成阶段可以先设为 -1 多试选定满意的图后把它的 seed 回填到 JSON 中作为稳定版本。2.4 批量渲染脚本下面的 Python 脚本读取 scenes.json并按镜头 ID 保存图片。它只展示核心逻辑实际项目中要加入日志、异常处理和已存在文件跳过机制。import base64 import json import requests from pathlib import Path API_URL http://127.0.0.1:7860/sdapi/v1/txt2img FRAMES_DIR Path(frames) FRAMES_DIR.mkdir(exist_okTrue) with open(scenes.json, r, encodingutf-8) as f: scene_data json.load(f) def render_scene(scene: dict) - list: payload { prompt: scene[prompt], negative_prompt: scene.get(negative_prompt, ), steps: scene.get(steps, 30), width: scene.get(width, 1024), height: scene.get(height, 576), cfg_scale: scene.get(cfg_scale, 7), batch_size: scene.get(batch_size, 1), seed: scene.get(seed, -1), sampler_name: scene.get(sampler_name, DPM 2M Karras), } resp requests.post(API_URL, jsonpayload, timeout300) resp.raise_for_status() return resp.json().get(images, []) for scene in scene_data[scenes]: shot_id scene[id] images render_scene(scene) for idx, img_b64 in enumerate(images): output_file FRAMES_DIR / fshot_{shot_id:02d}_{idx 1:02d}.png output_file.write_bytes(base64.b64decode(img_b64)) print(fsaved {output_file})batch_size可以控制一个镜头一次生成多少张候选图。建议每个镜头先生成 2 到 3 张挑出最合适的一张后续再固定 seed 重出正式版本。完整渲染时如果某个请求超时可以根据日志跳过这个镜头不要中断整批任务。注意批量任务开始前先手工生成一张图确认画面方向正确。一次性生成几十张后发现风格不对悔改成本很高。3. 静态帧之间不要只靠相同关键词连贯性要用种子和风格后缀锁住3.1 为什么相同关键词不能保证画面一致自制 MV 最常见的观感问题是每一张单图都好看连在一起却像来自完全不同作品。原因有两个画面主体不统一色彩风格不统一。同一镜头内反复生成时可以固定一个主体描述例如“旧厂区”“穿深色外套的男人”“小号”但随机种子不同人物五官、衣服褶皱、建筑轮廓都会变。如果前后两帧人物长得完全不一样观众立刻会觉得穿帮。解决方式并不是让 AI 画一部长视频而是控制镜头切换节奏。前奏通常只有几十秒不必把所有镜头做成连续动作可以使用“镜头切换 微弱推拉”的思路。一个镜头内部保持单张图片通过 FFmpeg 的推拉缩放产生运动感镜头之间切换时允许跳转但每个镜头内部的主体和画面结构要稳定。3.2 结构化提示词模板为了让不同镜头之间保有一致性把提示词拆成几个固定组件提示词组件作用示例基础介质锁定媒介风格film still, 35mm photo时间地点提供场景方向rain night, old industrial city主体内容控制画面对象man in dark jacket at window镜头语言控制景别和机位close-up, shallow depth of field色彩基调统一色调muted blue and orange, low saturation质感后缀统一胶片感film grain, natural skin texture在批量脚本里可以把不变的介质和色彩作为 style_suffix 拼在每句 prompt 后面。例如style_suffix , cinematic film still, 35mm, film grain, muted blue and orange, low saturation, natural skin texture一个城市夜景主体的最终提示词可以是film still, rain night, old industrial city, concrete apartments, wet road reflecting lights, cinematic composition, 35mm, film grain, muted blue and orange, low saturation人物的特写镜头则要在提示词中加入“皮肤细节”相关描述避免脸部异常close-up portrait of a middle-aged man in dim room, tired eyes, visible skin texture, fine pores, natural skin highlights, soft window light, cinematic film still, film grain这里提到的“皮肤细节”是在提示词质量控制层面说的。正面提示词里可以写“自然皮肤纹理、真实毛孔、自然皮肤高光”负面提示词里可以写“plastic skin, wax face, over-smooth face, airbrushed skin”。3.3 让画面连贯的种子和参考图做法同一镜头的正式重出可以使用两种做法第一种固定 seed。选定一张满意候选图后把对应 seed 写入 scenes.json之后重新提交完全相同的 prompt、negative_prompt、尺寸、采样器和 cfg_scale理论上能得到非常接近的图像。这种办法简单适合静态帧定稿。第二种把前一张合格图片作为 img2img 的输入并设置较低的 denoising。例如 denoising 控制在 0.25 到 0.4让 AI 在上一张画面的基础上调整细节这能让同一镜头里的连续帧更稳定。这种做法多用于一个镜头需要多帧连续画面而不是只做单张静态镜头。自制 MV 如果主要使用切换剪辑不一定需要每帧都连续可以先用固定种子方案。还要在负面提示词里统一排除不想要的东西。以下负面提示词可以成为基线text, watermark, frame, border, logo, signature, cartoon, painting, deformed face, bad anatomy, bad hands, extra fingers, extra limbs, oversaturated, plastic skin, wax face, over-smooth face注意负面提示词不要写得太重。负面提示词里写太多“不要 xxx”在某些模型里反而会触发不可预期的结果建议保留最关键的几类特别是肢体畸形、文字水印和过度磨皮。4. 用 FFmpeg 把 AI 静态图剪辑成前奏影像4.1 从单张静态图生成带运动感的视频片段静态图直接拼接观感接近幻灯片。要让它更像 MV需要给每个镜头加入缓慢推近或拉远的运动通常称为 Ken Burns 效果。FFmpeg 的 zoompan 滤镜可以实现这个效果。先看一个单镜头生成命令ffmpeg -y -i frames/shot_01_01.png \ -filter_complex scale3840:2160,zoompanzmin(zoom0.0015,1.10):xiw/2-(iw/zoom/2):yih/2-(ih/zoom/2):d225:s1920x1080:fps25 \ -frames:v 225 -c:v libx264 -crf 18 -pix_fmt yuv420p clips/clip_01.mp4这个命令的作用是先把原图放大到 3840x2160然后按每帧 0.0015 的比例慢慢拉近直到不超过 1.10 倍。d225 表示生成 225 帧在 25fps 下刚好是 9 秒。x 和 y 表达式让画面从中心缩放避免主体偏移到画面外。crf 18是较高质量数字越小质量越高。pix_fmt yuv420p是兼容性较好短视频软件普遍能播放。scale3840:2160是为了给 zoompan 留足放大空间避免画面放大后出现拼接块。实际项目中每个镜头长度不同可以按“秒数 x 帧率”计算 d 值。比如 8 秒、25fps 就是 200 帧。4.2 批量把多个分镜片段拼起来生成多个 clip 后需要按顺序拼接。FFmpeg 的 concat 拼接依赖固定列表文件file clips/clip_01.mp4 file clips/clip_02.mp4 file clips/clip_03.mp4用这段命令拼接ffmpeg -f concat -safe 0 -i list.txt -c copy clips/joined.mp4前提是所有 clip 使用完全相同的编码参数、分辨率和帧率否则-c copy可能失败。如果失败去掉-c copy让 FFmpeg 重新编码。转场也可以在此时处理。最安全的方式是在每个片段生成时加入淡入淡出例如前 0.5 秒淡入、后 0.5 秒淡出。这样拼接出来的视频不会生硬跳切。如果想做交叉溶解则处理相对复杂需要每个片段都有一定的重叠帧建议先不做用硬切加少量淡入淡出也能达到不错效果。4.3 把音频轨和视频轨对齐视频片段拼接完成后下一步是把音频接到时间轴上。这个环节的关键是前奏从哪里开始、到哪里结束。假设已经有一段合法使用的前奏音频 intro.mp3把它和视频合成ffmpeg -y -i clips/joined.mp4 -i audio/intro.mp3 \ -filter_complex [1:a]afadetin:st0:d0.5,afadetout:st6:d2[aout] \ -map 0:v -map [aout] -c:v copy -c:a aac -shortest output/ai_mv_final.mp4解释一下这段命令afadetin:st0:d0.5音频前 0.5 秒淡入避免突兀。afadetout:st6:d2从第 6 秒开始用 2 秒淡出。这里的时间要根据前奏实际长度调整。-c:v copy视频已经编码完成不需要二次编码处理速度快。-c:a aac输出 AAC 音频。-shortest按较短的一轨结束。音频文件的版权要提前确认。自制 MV 不等于可以随意使用任何商业歌曲。如果是学习流程最好使用自己在吉他或软件上录制的片段或者选择有明确授权、可自由使用的音频素材。技术流程可以复现版权风险必须自己规避。5. 成品输出检查、常见报错与排查顺序5.1 发布前检查清单生成 final 视频只是第一步真正能发布或留作作品还要完成以下检查检查项检查方式通过标准视频总时长ffprobe -show_entries formatduration -of csvp0 output/ai_mv_final.mp4与前奏长度接近分辨率与帧率ffprobe -show_streams output/ai_mv_final.mp4分辨率、帧率符合目标音频存在性播放时确认左右声道有声音不是静音首尾淡入淡出目测画面耳听音频无爆音、无突兀中断镜头主体一致性在播放器中逐段查看同一镜头内主体无明显变化异常帧暂停观察每张图无畸形人脸、无文字水印、无构图穿帮如果视频比前奏长可以删减部分镜头如果视频比前奏短需要返回 scenes.json 增加镜头时长或补充场景。在最终发布前把整个视频从头到尾看一遍不要只看缩略图或前几秒。5.2 常见问题与处理方案下面是制作过程中最容易遇到的问题整理成一张排查表问题现象常见原因检查方式处理方案同一镜头重复生成人物不一致未固定 seed 或提示词缺少主体描述对比两张图的 prompt 和 seed固定 seed把主体描述写到统一位置生成人物脸部像塑料负面提示词缺少皮肤相关问题或模型过度磨皮观察皮肤高光和毛孔加入 plastic skin, over-smooth face 等负面词正面加入 natural skin texture多张图风格分散每个场景提示词差异过大缺少风格后缀查看色彩、景别、画幅统一固定 style_suffixFFmpeg 拼接时报错“codec mismatch”不同片段编码参数不一致分别用 ffprobe 查看片段信息重新生成统一编码参数的片段或去掉-c copy重新编码画面推镜头后明显模糊zoompan 放大超出图片可用像素检查原图分辨率先把原图放大后再 zoompan 输出视频和音频不同步片段时长与音轨时长不一致使用 ffprobe 查看各片段时长回填 scenes.json 精确时长后重新渲染API 请求超时单图尺寸过大、显存不足查看生成工具日志降低分辨率、减小 batch_size5.3 排查顺序遇到问题不要先怀疑生成工具按下面顺序排查更快先检查输入。提示词、seed、尺寸、负面提示词是否按预期传入脚本存在 JSON 中的字段是否拼错。再检查环境和依赖。生图服务是否启动、API 地址是否正确、模型文件是否加载完整。然后检查配置。scenes.json 中宽高比、steps、cfg_scale 是否一致同一镜头是否误用了不同风格后缀。接着检查日志。API 返回了什么异常FFmpeg 输出是否提示编码器不匹配。最后才考虑升级硬件或更换模型。注意批量生图前先跑一个单镜头小样能省掉整批返工的时间。不要拿几十张图去验证一个错误参数。6. 把自制 MVAI 生图流程固化成可复用工作区6.1 一套可复用的操作顺序项目如果只跑一次脚本乱一点没问题。但前奏 MV 通常要改很多遍歌词意象、画面色调、音乐段落都可能在制作过程中调整。建议把工作流固化成固定顺序导出前奏音轨听三遍并标记情绪转折点。写分镜表明确每个镜头时长和画面方向。手工生成各镜头的第一版草图。确认风格后把 seed、prompt、negative_prompt 写入 scenes.json。批量渲染正式帧检查异常。用 FFmpeg 生成单片段确认推拉方向和速度。拼接片段插入音频。完整播放验证回到第 4 到第 7 步修改。这个顺序保证每次只改一个变量。比如只改色调时不要随手改 seed否则无法判断到底是因为色调变了还是因为随机性变了导致风格不一致。变量隔离是批量创作最值得养成的习惯。6.2 项目目录与命名规范用一套明确命名可以避免大量混乱。推荐方式镜头参数文件scenes.json原始帧shot_编号_候选序号.png单镜头视频clip_编号.mp4最终文件ai_mv_final.mp4不要用“新建文件夹2”“最终版3”这类命名会导致后面找人寻找、修复困难。每版成品可以在文件名中带日期或版本号例如ai_mv_final_v02.mp4旧版本保留但不要覆盖。6.3 从静态图到复杂视频的扩展方向这套流程跑通后可以往几个方向扩展第一加字幕。前奏如果有唱词或重要旁白需要把音频转写出来然后用 FFmpeg 的 drawtext 滤镜或字幕文件加入画面。drawtext 每帧渲染文字处理大量动态字幕时会消耗较多 CPU适合少字数场景。第二加更多的转场。把镜头切分为多个素材采用 xfade 滤镜做交叉溶解可以让画面更接近电影感。第三让静态图变成短动画。把每张图作为首帧再使用图生视频模型生成短暂动态片段。这需要额外的生成环境和更高显存但画面从“缓慢缩放的静态图”变成了“有小幅动作的视频”效果会有明显提升。第四做真正的批量工作流脚本。把 JSON 读取、API 请求、FFmpeg 合成整合到一个 Python 文件中传入一个新的 scenes.json就能生成另一支前奏短片。这样以后听到新歌前奏觉得有画面感不需要每次都从零开始搭流程。对想练手的新手来说最值得做的不是一开始追求复杂转场和精细动作而是先做一支“单镜头静态图 缓慢推拉 音频对齐”的完整小视频。只要时间轴清晰、画面风格统一、音画同步这支视频就已经具备完整结构。之后再逐步加入更多镜头、更复杂的转场和动画才能真正理解每一个处理环节是在解决什么问题。
返回列表