Сценарий отлично работает для большинства файлов, но он терпит неудачу всякий раз, когда имя файла субтитров содержит одну кавычку (апостроф), например, Вот и все.srt.
Когда скрипт встречает такой файл, Процесс ffmpeg немедленно завершается с ошибкой и не создает выходной файл. Это вызывает ошибку нисходящего потока KeyError: 'streams' в моем коде, когда он позже пытается запустить ffprobe для несуществующего выходного файла, но основной причиной является молчаливый сбой команды ffmpeg.
Единственное решение, которое я нашел, - это программно переименовать файл, чтобы удалить апостроф, чего я хочу избежать.
В первый раз, когда я столкнулся с этим, я прочитал вывел журнал и увидел, что ffmpeg сам удаляет апострофы из пути к строке, передаваемого в ffmpeg в коде.
Код: Выделить всё
[Parsed_subtitles_1 @ 000002c435dce5c0] Unable to open C:/FUBAR/Season 01/FUBAR - S01E08 - Thats It and Thats All.srt
Вот упрощенный пример того, как строка фильтра -vf и последняя команда ffmpeg создаются в моем скрипте:
Код: Выделить всё
import subprocess
from pathlib import Path
# --- Example of a problematic file path ---
source_video_path = Path(r"C:\videos\FUBAR - S01E08 - That's It and That's All.mkv")
subtitle_path = source_video_path.with_suffix('.srt')
# --- This is how I build the filter string ---
video_filter = 'crop=1920:800:0:140' # Example starting filter
# The subtitle path is formatted for the filter string
# NOTE: My real code finds this path dynamically.
formatted_subtitle_path = str(subtitle_path).replace('\\', '/')
# A simplified version of my style loop
style_string = "FontName=Segoe UI,FontSize=18,PrimaryColour=&H00FFFFFF"
# The filename is placed inside single quotes in the filter
video_filter += f",subtitles=filename='{formatted_subtitle_path}':force_style='{style_string}'"
# --- The final ffmpeg command list ---
command = [
'ffmpeg.exe',
'-y',
'-i', str(source_video_path),
'-vf', video_filter,
'-c:a', 'copy',
'output.mkv',
]
print("--- Generated FFmpeg Command ---")
# Using print to show how Python sees the arguments before execution
for i, arg in enumerate(command):
print(f"Arg[{i}]: {arg}")
# When run, ffmpeg fails on this command because of the ' in the filename.
# process = subprocess.run(command, text=True, capture_output=True)
# print("\n--- FFmpeg Output ---")
# print(process.stderr)
Я понимаю, что проблема в том, что одинарная кавычка в «Вот и все» преждевременно завершает строку filename='...' в фильтре -vf. Я пробовал несколько распространенных методов, чтобы избежать его, но ни один из них не сработал:
- Эскейпирование обратной косой черты: Я пробовал заменить апостроф в formatted_subtitle_path различными escape-последовательностями перед созданием строки фильтра.
Код: Выделить всё
replace("'", r"\'")Код: Выделить всё
replace("'", r"\\'")Код: Выделить всё
replace("'", r"\\\'")
- Трюк с цитированием оболочки: Я также попробовал метод '''.
Код: Выделить всё
replace("'", r"'\''") - Использование двойных кавычек: Я попытался изменить строку фильтра, чтобы заключить имя файла в двойные кавычки, но ffmpeg по-прежнему не работает.
Код: Выделить всё
video_filter += f""",subtitles=filename="{formatted_subtitle_path}":force_style=...Каков наиболее эффективный кроссплатформенный способ форматирования строки имени файла для фильтра субтитров ffmpeg, чтобы он мог правильно обрабатывать пути, содержащие одинарные кавычки?
Подробнее здесь: https://stackoverflow.com/questions/797 ... tles-filte