Spaces:
Sleeping
Sleeping
Download skill/scripts/video_decode_check.py from cpuai/ahp-development-workstation: direct link, hf CLI and curl.
- Browser
- Download file 2.18 kB
-
https://huggingface.co/spaces/cpuai/ahp-development-workstation/resolve/main/skill/scripts/video_decode_check.py
- Command line
-
hf download hf://spaces/cpuai/ahp-development-workstation/skill/scripts/video_decode_check.py
-
curl -L -o video_decode_check.py https://huggingface.co/spaces/cpuai/ahp-development-workstation/resolve/main/skill/scripts/video_decode_check.py
2.18 kB
| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| """科普视频成片完整技术审查(比 ffprobe 文件头检查更严格)。 | |
| 完整解码所有帧并检查音频存在。该脚本不判断科学事实是否正确。 | |
| """ | |
| from __future__ import annotations | |
| import argparse,json,subprocess,sys | |
| from pathlib import Path | |
| def run(path:Path,expected_width=1080,expected_height=1920,expected_fps=30): | |
| if not path.is_file():raise FileNotFoundError(path) | |
| obj=json.loads(subprocess.check_output(['ffprobe','-v','error','-show_format','-show_streams','-of','json',str(path)],text=True)) | |
| video=next((x for x in obj['streams'] if x.get('codec_type')=='video'),None) | |
| audio=next((x for x in obj['streams'] if x.get('codec_type')=='audio'),None) | |
| assert video and audio,'Missing audio or video' | |
| actual_rate=video.get('avg_frame_rate',video.get('r_frame_rate','0/1')) | |
| numerator,denominator=map(float,actual_rate.split('/')) | |
| assert denominator and abs(numerator/denominator-expected_fps)<.12 | |
| assert video.get('width')==expected_width and video.get('height')==expected_height | |
| assert video.get('codec_name')=='h264' and audio.get('codec_name')=='aac' | |
| # Prevent writing garbage to stdout or disk: decode both streams into null sink. | |
| proc=subprocess.run(['ffmpeg','-hide_banner','-nostdin','-v','error','-xerror','-i',str(path),'-f','null','-'],capture_output=True,text=True) | |
| if proc.returncode:raise RuntimeError('Full decode failed: '+proc.stderr[-1500:]) | |
| return {'file':str(path),'duration':round(float(obj['format']['duration']),3),'fps':actual_rate,'video_codec':video['codec_name'],'audio_codec':audio['codec_name'],'whole_movie_decode_ok':True} | |
| if __name__=='__main__': | |
| p=argparse.ArgumentParser();p.add_argument('video');p.add_argument('--width',type=int,default=1080);p.add_argument('--height',type=int,default=1920);p.add_argument('--fps',type=int,default=30);a=p.parse_args() | |
| try: | |
| report=run(Path(a.video),a.width,a.height,a.fps) | |
| print(json.dumps(report,ensure_ascii=False,indent=2)) | |
| except Exception as e: | |
| print(json.dumps({'qa_pass':False,'error':str(e)},ensure_ascii=False));sys.exit(2) | |