add find-av1
This commit is contained in:
parent
be2fd9d32f
commit
368aec13dc
123
find-av1/find_av1.py
Normal file
123
find-av1/find_av1.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
import platform
|
||||||
|
import shutil # 用于检查 ffprobe 是否存在
|
||||||
|
|
||||||
|
# 常见的视频文件扩展名列表 (可以根据需要添加或删除)
|
||||||
|
VIDEO_EXTENSIONS = {
|
||||||
|
'.mp4', '.mkv', '.webm', '.avi', '.mov', '.flv', '.wmv', '.ts', '.m2ts'
|
||||||
|
}
|
||||||
|
|
||||||
|
def check_ffprobe():
|
||||||
|
"""检查 ffprobe 是否在系统 PATH 中可用"""
|
||||||
|
ffprobe_path = shutil.which('ffprobe')
|
||||||
|
if not ffprobe_path:
|
||||||
|
print("错误: 'ffprobe' 命令未找到。请确保 FFmpeg 已正确安装并添加到系统环境变量 PATH 中。", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
print(f"找到 ffprobe: {ffprobe_path}")
|
||||||
|
return ffprobe_path
|
||||||
|
|
||||||
|
def get_video_codec(file_path, ffprobe_path):
|
||||||
|
"""使用 ffprobe 获取视频文件的第一个视频流的编码名称"""
|
||||||
|
command = [
|
||||||
|
ffprobe_path,
|
||||||
|
'-v', 'error', # 只输出错误信息
|
||||||
|
'-select_streams', 'v:0', # 选择第一个视频流
|
||||||
|
'-show_entries', 'stream=codec_name', # 只显示流的编码名称
|
||||||
|
'-of', 'default=noprint_wrappers=1:nokey=1', # 输出格式: 只输出值
|
||||||
|
file_path
|
||||||
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 在 Windows 上,隐藏命令行窗口
|
||||||
|
startupinfo = None
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
startupinfo = subprocess.STARTUPINFO()
|
||||||
|
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||||
|
startupinfo.wShowWindow = subprocess.SW_HIDE
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
command,
|
||||||
|
capture_output=True, # 捕获标准输出和标准错误
|
||||||
|
text=True, # 以文本模式处理输出 (自动解码)
|
||||||
|
check=False, # 不在 ffprobe 返回非零时抛出异常,手动检查
|
||||||
|
startupinfo=startupinfo # 隐藏 Windows 上的窗口
|
||||||
|
)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
# ffprobe 执行出错 (可能是文件损坏或非视频文件)
|
||||||
|
# print(f"警告: 处理文件 '{file_path}' 时 ffprobe 出错: {result.stderr.strip()}", file=sys.stderr)
|
||||||
|
return None # 返回 None 表示无法确定编码
|
||||||
|
|
||||||
|
codec_name = result.stdout.strip()
|
||||||
|
return codec_name if codec_name else None # 如果输出为空也返回 None
|
||||||
|
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"错误: 无法执行 '{ffprobe_path}'。请确保它在您的 PATH 中。", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"错误: 处理文件 '{file_path}' 时发生未知错误: {e}", file=sys.stderr)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def find_av1_videos(directory, ffprobe_path):
|
||||||
|
"""在指定目录及其子目录中查找 AV1 编码的视频文件"""
|
||||||
|
print(f"\n正在扫描目录: {directory}")
|
||||||
|
av1_files_count = 0
|
||||||
|
processed_files_count = 0
|
||||||
|
|
||||||
|
for root, _, files in os.walk(directory):
|
||||||
|
for filename in files:
|
||||||
|
# 检查文件扩展名是否在视频扩展名列表中
|
||||||
|
_, ext = os.path.splitext(filename)
|
||||||
|
if ext.lower() in VIDEO_EXTENSIONS:
|
||||||
|
file_path = os.path.join(root, filename)
|
||||||
|
processed_files_count += 1
|
||||||
|
print(f" 正在检查: {file_path}", end='\r', flush=True) # 显示当前检查的文件
|
||||||
|
|
||||||
|
codec = get_video_codec(file_path, ffprobe_path)
|
||||||
|
|
||||||
|
# 清除行尾的 "正在检查..."
|
||||||
|
print(" " * (len(file_path) + 15), end='\r', flush=True)
|
||||||
|
|
||||||
|
if codec == 'av1':
|
||||||
|
print(f" [AV1] {file_path}") # 找到 AV1 文件,打印完整路径
|
||||||
|
av1_files_count += 1
|
||||||
|
# elif codec: # 可选:打印非 AV1 视频的编码
|
||||||
|
# print(f" [{codec.upper()}] {file_path}")
|
||||||
|
# else: # 可选:打印无法处理的文件
|
||||||
|
# print(f" [无法识别/错误] {file_path}")
|
||||||
|
|
||||||
|
|
||||||
|
print(f"\n扫描完成。共处理 {processed_files_count} 个可能的视频文件,找到 {av1_files_count} 个 AV1 编码视频。")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="在指定目录及其子目录中查找所有 AV1 编码的视频文件。",
|
||||||
|
epilog="需要系统安装 FFmpeg 并将 ffprobe 添加到环境变量 PATH。"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"directory",
|
||||||
|
help="要扫描的根目录路径。"
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
target_directory = args.directory
|
||||||
|
|
||||||
|
# 检查目录是否存在
|
||||||
|
if not os.path.isdir(target_directory):
|
||||||
|
print(f"错误: 目录 '{target_directory}' 不存在或不是一个有效的目录。", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# 检查 ffprobe 是否可用
|
||||||
|
ffprobe_executable = check_ffprobe()
|
||||||
|
|
||||||
|
# 开始查找
|
||||||
|
find_av1_videos(target_directory, ffprobe_executable)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
61
find-av1/readme.md
Normal file
61
find-av1/readme.md
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# AV1 视频查找器 (AV1 Video Finder)
|
||||||
|
|
||||||
|
这是一个跨平台 (Windows, macOS, Linux) 的 Python 脚本,用于扫描指定目录及其所有子目录,找出所有使用 AV1 视频编码的视频文件。
|
||||||
|
|
||||||
|
## 功能
|
||||||
|
|
||||||
|
* 递归扫描指定目录下的所有文件。
|
||||||
|
* 通过文件扩展名初步过滤出可能的视频文件。
|
||||||
|
* 使用 `ffprobe` (FFmpeg 套件的一部分) 来准确识别视频文件的视频流编码。
|
||||||
|
* 输出所有检测到的 AV1 编码视频文件的完整路径。
|
||||||
|
* 显示扫描进度和最终统计结果。
|
||||||
|
|
||||||
|
## 先决条件
|
||||||
|
|
||||||
|
1. **Python 3.x**: 需要安装 Python 3。你可以从 [python.org](https://www.python.org/) 下载。
|
||||||
|
2. **FFmpeg**: 需要在你的系统上安装 FFmpeg。脚本实际上使用的是 `ffprobe` 命令,它通常随 FFmpeg 一起安装。
|
||||||
|
* **重要**: `ffprobe` 的可执行文件必须位于系统的环境变量 `PATH` 中,这样脚本才能直接调用它。
|
||||||
|
* **检查方法**: 打开你的终端或命令提示符,输入 `ffprobe -version` 或 `ffmpeg -version`。如果命令能够成功执行并显示版本信息,则表示配置正确。如果提示找不到命令,你需要将 FFmpeg 的 `bin` 目录添加到系统的 `PATH` 环境变量中。
|
||||||
|
|
||||||
|
## 如何使用
|
||||||
|
|
||||||
|
1. **保存脚本**: 将上面的 Python 代码保存为 `find_av1.py` 文件。
|
||||||
|
2. **打开终端或命令提示符**:
|
||||||
|
* **Windows**: 可以使用 `cmd.exe` 或 `PowerShell`。
|
||||||
|
* **macOS**: 使用 `Terminal.app`。
|
||||||
|
* **Linux**: 使用你常用的终端模拟器 (如 `gnome-terminal`, `konsole`, `xterm` 等)。
|
||||||
|
3. **运行脚本**: 使用 `python` 命令执行脚本,并提供要扫描的目录作为参数。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python find_av1.py /path/to/your/video/directory
|
||||||
|
```
|
||||||
|
|
||||||
|
或者 (在 macOS/Linux 上,如果添加了执行权限 `chmod +x find_av1.py`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./find_av1.py /path/to/your/video/directory
|
||||||
|
```
|
||||||
|
|
||||||
|
**请将 `/path/to/your/video/directory` 替换为你要扫描的实际目录路径。**
|
||||||
|
|
||||||
|
* **示例 (Windows)**: `python find_av1.py C:\Users\YourUser\Videos`
|
||||||
|
* **示例 (macOS/Linux)**: `python find_av1.py /home/youruser/media/movies`
|
||||||
|
|
||||||
|
4. **查看输出**: 脚本会首先检查 `ffprobe` 是否可用,然后开始扫描。它会实时更新当前正在检查的文件,并在找到 AV1 视频时打印其完整路径。扫描结束后,会显示总共处理的文件数和找到的 AV1 文件数。
|
||||||
|
|
||||||
|
## 工作原理
|
||||||
|
|
||||||
|
1. 脚本接收一个目录路径作为输入。
|
||||||
|
2. 使用 `os.walk` (或类似方法,这里用了`os.walk`来遍历目录结构) 遍历该目录及其所有子目录中的文件。
|
||||||
|
3. 对于每个文件,检查其扩展名是否属于常见的视频格式 (定义在 `VIDEO_EXTENSIONS` 集合中)。
|
||||||
|
4. 如果扩展名匹配,脚本会调用 `ffprobe` 命令来查询该文件的第一个视频流 (`-select_streams v:0`) 的编码名称 (`stream=codec_name`)。
|
||||||
|
5. `ffprobe` 的输出 (即编码名称) 被捕获。
|
||||||
|
6. 如果编码名称是 `av1`,则该文件的路径被打印到控制台。
|
||||||
|
7. 处理过程中会捕获并报告 `ffprobe` 执行可能发生的错误 (如文件损坏、非视频文件等),但不会中断整个扫描过程。
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
* 脚本依赖于 `ffprobe` 来识别编码,识别的准确性取决于 `ffprobe`。
|
||||||
|
* 扫描大型目录或包含大量视频文件的目录可能需要较长时间,因为每个潜在的视频文件都需要调用 `ffprobe` 进行分析。
|
||||||
|
* `VIDEO_EXTENSIONS` 列表包含了常见的视频格式,但可能不是最全的。如果你的 AV1 视频使用了不常见的扩展名,可以编辑脚本将该扩展名添加到列表中。
|
||||||
|
* 如果文件没有视频流,或者 `ffprobe` 因文件损坏等原因无法读取元数据,该文件将被跳过。
|
Loading…
x
Reference in New Issue
Block a user