ReVID / data_test.py
GuoruiSong's picture
Add files using upload-large-folder tool
3e90852 verified
Raw
History Blame Contribute Delete
3.96 kB
import json
import os
import numpy as np
from tqdm import tqdm
from concurrent.futures import ProcessPoolExecutor, as_completed
import decord
from decord import VideoReader, cpu
# 屏蔽底层烦人的 C++ 报错输出
# decord.bridge.set_bridge('torch')
import logging
decord.logging.set_level(logging.ERROR)
# 🌟 模拟你修复后的训练配置
class DataArgs:
def __init__(self):
self.video_fps = 1
self.frames_upbound = 16 # 保持和你训练时设置的上限一致
self.force_sample = True
data_args = DataArgs()
def check_single_sample(item):
"""
核心验证逻辑:完全复刻训练时的视频抽帧代码
只有通过了真实 get_batch 考验的视频,才算真正的“好数据”
"""
video_path = item.get("video_abs_path")
if not video_path or not os.path.exists(video_path):
return False, item, "文件不存在或路径为空"
try:
# 完全照搬你的 process_video_with_decord 逻辑
vr = VideoReader(video_path, ctx=cpu(0), num_threads=1)
total_frame_num = len(vr)
if total_frame_num == 0:
return False, item, "视频总帧数为 0"
avg_fps = round(vr.get_avg_fps() / data_args.video_fps)
if avg_fps <= 0:
avg_fps = 1
frame_idx = [i for i in range(0, total_frame_num, avg_fps)]
if data_args.frames_upbound > 0:
if len(frame_idx) > data_args.frames_upbound or data_args.force_sample:
uniform_sampled_frames = np.linspace(0, total_frame_num - 1, data_args.frames_upbound, dtype=int)
frame_idx = uniform_sampled_frames.tolist()
# 🚨 终极考验:尝试真实提取这批帧!坏视频在这里一定会原形毕露崩溃
video = vr.get_batch(frame_idx).asnumpy()
if video.shape[0] == 0:
return False, item, "提取到的帧矩阵为空"
return True, item, "OK"
except Exception as e:
# 捕获所有 decord 底层抛出的异常 (包括你遇到的 h264 错误)
return False, item, f"解码崩溃: {str(e)}"
def run_deep_clean(input_json, clean_json, bad_json, num_workers=16):
print(f"正在读取数据集: {input_json} ...")
with open(input_json, 'r') as f:
data_list = json.load(f)
# data_list = data_list[5000:5100]
clean_data = []
bad_data = []
print(f"\n🚀 开始深度清洗 {len(data_list)} 条数据 (启用 {num_workers} 个进程并发)...")
# 使用进程池极大加快处理速度
with ProcessPoolExecutor(max_workers=num_workers) as executor:
futures = [executor.submit(check_single_sample, item) for item in data_list]
for future in tqdm(as_completed(futures), total=len(data_list), desc="🔨 质检进度"):
is_valid, item, error_msg = future.result()
if is_valid:
clean_data.append(item)
else:
item['error_reason'] = error_msg
bad_data.append(item)
print("\n" + "="*50)
print(f"✅ 清洗彻底完成!")
print(f"🎉 纯净数据: {len(clean_data)} 条 -> 已保存至 {clean_json}")
print(f"☠️ 损毁数据: {len(bad_data)} 条 -> 已保存至 {bad_json}")
print("="*50)
with open(clean_json, 'w') as f:
json.dump(clean_data, f, indent=4)
with open(bad_json, 'w') as f:
json.dump(bad_data, f, indent=4)
if __name__ == "__main__":
# 替换成你当前的 JSON 路径
INPUT_FILE = "./data/video_reversal_sft_train_cleaned_10k.json"
CLEAN_FILE = "./data/video_reversal_sft_train_ultra_clean.json"
BAD_FILE = "./data/video_reversal_sft_train_bad_samples.json"
# 根据你机器的 CPU 核心数调整 num_workers,核心越多越快
run_deep_clean(INPUT_FILE, CLEAN_FILE, BAD_FILE, num_workers=16)