先分清两件事:参考图决定「脸本身有没有足够的细节可还原」,帧数与时长决定「细节在逐帧生成里被消耗多久」。Wan-Dancer 类图生视频模型的人脸越跳越糊,多数不是某个参数没调对,而是退化随帧累积叠加,再被输出编码放大。所以不要一上来就调大采样步数或换更大模型,先把「糊」变成可对比的帧号,再逐项换掉变量:同一段驱动下,换参考图看退化帧号是否后移,缩短时长看退化是否消失,最后用 ffprobe 确认后处理没有二次损失。
处理顺序建议是:抽帧建联系表定位人脸开始退化的帧号 → 换高分辨率正脸参考图重跑同一段驱动 → 用长短两档帧数对比退化帧号 → 核对编码与放大环节。哪一层的改动让退化帧号明显后移,问题就落在那层;如果换参考图、缩短时长都无效,优先怀疑输出编码或放大链路,而不是继续加参数。
在输出视频里定位人脸开始退化的具体帧号
「越跳越糊」是主观描述,先把它变成一行行帧号记录。抽帧时不要求全量,隔几帧取一张就够定位趋势;关键是让每个缩略图能对上原视频帧号,否则后面换参考图重跑就没法做同帧对比。
# 1) 按固定间隔抽帧,输出带真实帧号与时间戳的日志
ffmpeg -i out.mp4 -vf "select='not(mod(n,15))',showinfo" -fps_mode passthrough \
-f null - 2>&1 | grep -E "n: *[0-9]+ .*pts_time" > frame_index.log
# 2) 抽成小图,方便肉眼扫
mkdir -p frames
ffmpeg -i out.mp4 -vf "select='not(mod(n,15))',scale=360:-1" -fps_mode passthrough frames/f_%05d.png
# 3) 拼成联系表,一张图看完整段
ffmpeg -i out.mp4 -vf "select='not(mod(n,15))',scale=320:-1,tile=6x5" \
-fps_mode passthrough -frames:v 1 sheet_%02d.jpg
把mod(n,15)里的 15 换成你自己的采样步长,采样越密,退化起点定得越准。打开 sheet_01.jpg 逐格看,找到第一个「五官还能分辨、但轮廓开始粘连」的格子,回到 frame_index.log 里取对应帧号,记成退化起点;再往后找一格「已经分不清眼睛和眉毛」的,记成完全糊化帧。这两个帧号就是后面所有对比的锚点。建议先用 2 倍速、单窗口播放确认,避免把压缩块效应误判成生成退化。
换一张高分辨率正脸参考图重跑同一段驱动
这一步只改参考图一个变量,其他参数保持上一轮原样,驱动音频或动作序列也用同一段。参考图要求通常是:正脸、五官无遮挡、头部占画面主体、没有强滤镜和明显磨皮、边长不低于最终输出分辨率的人脸区域像素数。侧脸、低头、半张脸出画、背景比脸还抢细节的图,都不适合用来做排除实验。
# 以原图中心为基准裁一个接近正方形的正脸区域,再统一缩放
ffmpeg -i ref_src.jpg -vf "crop=iw*0.7:ih*0.7,scale=768:768:flags=lanczos" -q:v 2 ref_face.jpg
# 裁完确认人脸占比和清晰度,别只看尺寸
ffprobe -v error -select_streams v:0 -show_entries stream=width,height,pix_fmt -of default=nw=1 ref_face.jpg
裁切比例按实际构图调整,0.7 只是起点;如果人脸本来就小,先放大再裁会引入插值模糊,这种情况建议重新提供一张更近的原图,而不是靠缩放硬凑。重跑后回到同一个帧号,把新旧两版的该帧并排放:如果新参考图下退化起点明显后移,甚至到片尾才出现,说明原参考图细节不足是主因;如果退化帧号基本不变,参考图这条变量就可以排除了。
缩短生成时长,看退化是否被推迟
这一轮改的是帧数与时长。多数 Wan-Dancer 类配置把总帧数、帧率、时长拆成几个字段,位置通常在推理配置或任务提交参数里,字段名可能是 num_frames、video_length、fps 之类,需要结合你实际用的仓库或页面确认。设两档做对比即可,不必扫参数空间。
# 通用配置骨架,字段名按你的实际接入替换
run_a:
ref_image: ref_face.jpg
driver: same_clip
num_frames: 81 # 长档
fps: 16
seed: 1234
run_b:
ref_image: ref_face.jpg
driver: same_clip
num_frames: 33 # 短档
fps: 16
seed: 1234
两档都跑完后,各抽一次联系表,分别记录退化起点帧号和完全糊化帧。判断标准是看「单位时间内的退化速度」:如果短档在相同帧号位置依然糊,说明不是帧数累积导致,而是从早期就存在的问题;如果短档整段都干净、长档后半段才糊,说明退化随帧累积加重,这时优先考虑分段生成再拼接,而不是继续拉长单次生成。分段拼接要注意衔接帧的一致性,接缝处同样需要用抽帧检查。
核对输出编码与放大环节有没有二次损失
生成侧看着还行、导出后更糊的情况并不少见:低码率、错误的像素格式、多余的缩放,都会在最后一公里吃掉人脸细节。先读实际输出参数,别凭配置猜。
ffprobe -v error -select_streams v:0 \
-show_entries stream=codec_name,width,height,pix_fmt,bit_rate,avg_frame_rate \
-show_entries format=bit_rate,duration \
-of default=nw=1 out.mp4
重点看三处:pix_fmt 是否为你预期的格式(常见 yuv420p,如果上游是 4:4:4 或 rgb,转 420 会损失色度细节,边缘更容易发虚);bit_rate 相对分辨率和帧率是否偏低;width/height 是否与生成分辨率一致——不一致说明中间做过缩放。编码建议用可控质量的参数而不是固定码率:
ffmpeg -i gen_raw.mp4 -c:v libx264 -crf 18 -preset slow \
-pix_fmt yuv420p -movflags +faststart out_check.mp4
如果放大环节用了超分或插帧,把这一环临时关掉,用同样命令再导一次,对比同一帧的人脸纹理:关闭后更清楚,就说明放大没带来收益反而引入模糊,应回到原分辨率输出,或把放大放在生成前对参考图做。所有对比都以同一帧号、同一裁切区域为准,避免不同缩放比例造成的错觉。
把对照结论固化成默认参数
三轮对比下来,通常只有一两个变量真正影响退化帧号。把记录整理成表,写回默认配置,下次出片就不用重新试。建议的对照表字段如下,一行一次实验,帧号都填同一套口径:
- 实验编号 / 时间
- 参考图文件名与边长、人脸占比
num_frames与fps、对应时长- 生成分辨率
- 退化起点帧号 / 完全糊化帧号
- 输出编码参数(codec、crf、pix_fmt)与是否经过放大
- 备注:该次只改了哪个变量
最终参数写回你实际的出片配置位置:如果是脚本调用,落在推理配置或命令行默认值里;如果是页面操作,把固定下来的参考图预处理方式、帧数档位和导出编码参数记在团队的任务模板中,并在模板里附一句「换参考图后需重跑一次同帧对比」。判断边界也要写清楚:本轮的退化帧号只在这套参考图、这段驱动、这档分辨率下成立,换素材或换模型版本都要重新确认,不要直接套用旧结论。