🐛 fix(av1-transfer): use preexec_fn+os.execvp to rename ffmpeg argv[0]

execve with explicit paths fails on this system (linuxbrew symlink issue).
os.execvp in preexec_fn uses PATH lookup which works, and since it replaces
the child process before subprocess's own exec runs, pipes are inherited correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
FlintyLemming
2026-02-28 11:19:11 +08:00
parent af3c55d3c7
commit 79e19229af

View File

@@ -19,8 +19,8 @@ AV1 视频批量转码脚本
import argparse import argparse
import ctypes import ctypes
import ctypes.util import ctypes.util
import os
import queue import queue
import shlex
import shutil import shutil
import subprocess import subprocess
import sys import sys
@@ -130,21 +130,23 @@ def transcode_one_file(file_info, overall_bar, slot_bars, slot_queue, process_na
str(output_path), str(output_path),
] ]
str_args = [str(a) for a in ffmpeg_args]
if process_name: if process_name:
# 用 bash 的 exec -a 重命名 ffmpeg 进程的 argv[0] # fork 后、subprocess 执行 exec 之前,用 os.execvp 替换进程:
# ffmpeg 通过 PATH 查找,避免 execve 直接调用 symlink 的兼容问题 # - execvp 通过 PATH 查找 ffmpeg规避 execve 直接调用 symlink 的问题
shell_args = " ".join(shlex.quote(str(a)) for a in ffmpeg_args) # - argv[0] 设为别名ps/top 显示别名而非 ffmpeg
sh = shutil.which("sh") or shutil.which("bash") or "/usr/bin/sh" # - subprocess 设好的 stdout/stderr pipe 已继承,无需额外处理
_pname = process_name
_args = str_args
proc = subprocess.Popen( proc = subprocess.Popen(
f"exec -a {shlex.quote(process_name)} ffmpeg {shell_args}", ["ffmpeg"] + str_args,
shell=True, preexec_fn=lambda: os.execvp("ffmpeg", [_pname] + _args),
executable=sh,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
) )
else: else:
proc = subprocess.Popen( proc = subprocess.Popen(
["ffmpeg"] + ffmpeg_args, ["ffmpeg"] + str_args,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
) )