SoniTranslate / soni_translate /preprocessor.py
r3gm's picture
test hevc
055379d verified
raw
history blame
13.3 kB
from .utils import remove_files
import os, shutil, subprocess, time, shlex, sys # noqa
from .logging_setup import logger
import json
ERROR_INCORRECT_CODEC_PARAMETERS = [
"prores", # mov
"ffv1", # mkv
"msmpeg4v3", # avi
"wmv2", # wmv
"theora", # ogv
] # fix final merge
TESTED_CODECS = [
"h264", # mp4
"h265", # mp4
"hevc", # test
"vp9", # webm
"mpeg4", # mp4
"mpeg2video", # mpg
"mjpeg", # avi
]
class OperationFailedError(Exception):
def __init__(self, message="The operation did not complete successfully."):
self.message = message
super().__init__(self.message)
def get_video_codec(video_file):
command_base = rf'ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of json "{video_file}"'
command = shlex.split(command_base)
try:
process = subprocess.Popen(
command,
stdout=subprocess.PIPE,
creationflags=subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0,
)
output, _ = process.communicate()
codec_info = json.loads(output.decode('utf-8'))
codec_name = codec_info['streams'][0]['codec_name']
return codec_name
except Exception as error:
logger.debug(str(error))
return None
def audio_preprocessor(preview, base_audio, audio_wav, use_cuda=False):
base_audio = base_audio.strip()
previous_files_to_remove = [audio_wav]
remove_files(previous_files_to_remove)
if preview:
logger.warning(
"Creating a preview video of 10 seconds, to disable "
"this option, go to advanced settings and turn off preview."
)
wav_ = f'ffmpeg -y -i "{base_audio}" -ss 00:00:20 -t 00:00:10 -vn -acodec pcm_s16le -ar 44100 -ac 2 audio.wav'
else:
wav_ = f'ffmpeg -y -i "{base_audio}" -vn -acodec pcm_s16le -ar 44100 -ac 2 audio.wav'
# Run cmd process
sub_params = {
"stdout": subprocess.PIPE,
"stderr": subprocess.PIPE,
"creationflags": subprocess.CREATE_NO_WINDOW
if sys.platform == "win32"
else 0,
}
wav_ = shlex.split(wav_)
result_convert_audio = subprocess.Popen(wav_, **sub_params)
output, errors = result_convert_audio.communicate()
time.sleep(1)
if result_convert_audio.returncode in [1, 2] or not os.path.exists(
audio_wav
):
raise OperationFailedError(f"Error can't create the audio file:\n{errors.decode('utf-8')}")
def audio_video_preprocessor(
preview, video, OutputFile, audio_wav, use_cuda=False
):
video = video.strip()
previous_files_to_remove = [OutputFile, "audio.webm", audio_wav]
remove_files(previous_files_to_remove)
if os.path.exists(video):
if preview:
logger.warning(
"Creating a preview video of 10 seconds, "
"to disable this option, go to advanced "
"settings and turn off preview."
)
mp4_ = f'ffmpeg -y -i "{video}" -ss 00:00:20 -t 00:00:10 -c:v libx264 -c:a aac -strict experimental Video.mp4'
else:
video_codec = get_video_codec(video)
if not video_codec:
logger.debug("No video codec found in video")
else:
logger.info(f"Video codec: {video_codec}")
# Check if the file ends with ".mp4" extension or is valid codec
if video.endswith(".mp4") or video_codec in TESTED_CODECS:
destination_path = os.path.join(os.getcwd(), "Video.mp4")
shutil.copy(video, destination_path)
time.sleep(0.5)
if os.path.exists(OutputFile):
mp4_ = "ffmpeg -h"
else:
mp4_ = f'ffmpeg -y -i "{video}" -c copy Video.mp4'
else:
logger.warning(
"File does not have the '.mp4' extension or a "
"supported codec. Converting video to mp4 (codec: h264)."
)
mp4_ = f'ffmpeg -y -i "{video}" -c:v libx264 -c:a aac -strict experimental Video.mp4'
else:
if preview:
logger.warning(
"Creating a preview from the link, 10 seconds "
"to disable this option, go to advanced "
"settings and turn off preview."
)
# https://github.com/yt-dlp/yt-dlp/issues/2220
mp4_ = f'yt-dlp -f "mp4" --downloader ffmpeg --downloader-args "ffmpeg_i: -ss 00:00:20 -t 00:00:10" --force-overwrites --max-downloads 1 --no-warnings --no-playlist --no-abort-on-error --ignore-no-formats-error --restrict-filenames -o {OutputFile} {video}'
wav_ = "ffmpeg -y -i Video.mp4 -vn -acodec pcm_s16le -ar 44100 -ac 2 audio.wav"
else:
mp4_ = f'yt-dlp -f "mp4" --force-overwrites --max-downloads 1 --no-warnings --no-playlist --no-abort-on-error --ignore-no-formats-error --restrict-filenames -o {OutputFile} {video}'
wav_ = f"python -m yt_dlp --output {audio_wav} --force-overwrites --max-downloads 1 --no-warnings --no-playlist --no-abort-on-error --ignore-no-formats-error --extract-audio --audio-format wav {video}"
# Run cmd process
mp4_ = shlex.split(mp4_)
sub_params = {
"stdout": subprocess.PIPE,
"stderr": subprocess.PIPE,
"creationflags": subprocess.CREATE_NO_WINDOW
if sys.platform == "win32"
else 0,
}
if os.path.exists(video):
logger.info("Process video...")
result_convert_video = subprocess.Popen(mp4_, **sub_params)
# result_convert_video.wait()
output, errors = result_convert_video.communicate()
time.sleep(1)
if result_convert_video.returncode in [1, 2] or not os.path.exists(
OutputFile
):
raise OperationFailedError(f"Error processing video:\n{errors.decode('utf-8')}")
logger.info("Process audio...")
wav_ = "ffmpeg -y -i Video.mp4 -vn -acodec pcm_s16le -ar 44100 -ac 2 audio.wav"
wav_ = shlex.split(wav_)
result_convert_audio = subprocess.Popen(wav_, **sub_params)
output, errors = result_convert_audio.communicate()
time.sleep(1)
if result_convert_audio.returncode in [1, 2] or not os.path.exists(
audio_wav
):
raise OperationFailedError(f"Error can't create the audio file:\n{errors.decode('utf-8')}")
else:
wav_ = shlex.split(wav_)
if preview:
result_convert_video = subprocess.Popen(mp4_, **sub_params)
output, errors = result_convert_video.communicate()
time.sleep(0.5)
result_convert_audio = subprocess.Popen(wav_, **sub_params)
output, errors = result_convert_audio.communicate()
time.sleep(0.5)
if result_convert_audio.returncode in [1, 2] or not os.path.exists(
audio_wav
):
raise OperationFailedError(
f"Error can't create the preview file:\n{errors.decode('utf-8')}"
)
else:
logger.info("Process audio...")
result_convert_audio = subprocess.Popen(wav_, **sub_params)
output, errors = result_convert_audio.communicate()
time.sleep(1)
if result_convert_audio.returncode in [1, 2] or not os.path.exists(
audio_wav
):
raise OperationFailedError(f"Error can't download the audio:\n{errors.decode('utf-8')}")
logger.info("Process video...")
result_convert_video = subprocess.Popen(mp4_, **sub_params)
output, errors = result_convert_video.communicate()
time.sleep(1)
if result_convert_video.returncode in [1, 2] or not os.path.exists(
OutputFile
):
raise OperationFailedError(f"Error can't download the video:\n{errors.decode('utf-8')}")
def old_audio_video_preprocessor(preview, video, OutputFile, audio_wav):
previous_files_to_remove = [OutputFile, "audio.webm", audio_wav]
remove_files(previous_files_to_remove)
if os.path.exists(video):
if preview:
logger.warning(
"Creating a preview video of 10 seconds, "
"to disable this option, go to advanced "
"settings and turn off preview."
)
command = f'ffmpeg -y -i "{video}" -ss 00:00:20 -t 00:00:10 -c:v libx264 -c:a aac -strict experimental Video.mp4'
result_convert_video = subprocess.run(
command, capture_output=True, text=True, shell=True
)
else:
# Check if the file ends with ".mp4" extension
if video.endswith(".mp4"):
destination_path = os.path.join(os.getcwd(), "Video.mp4")
shutil.copy(video, destination_path)
result_convert_video = {}
result_convert_video = subprocess.run(
"echo Video copied",
capture_output=True,
text=True,
shell=True,
)
else:
logger.warning(
"File does not have the '.mp4' extension. Converting video."
)
command = f'ffmpeg -y -i "{video}" -c:v libx264 -c:a aac -strict experimental Video.mp4'
result_convert_video = subprocess.run(
command, capture_output=True, text=True, shell=True
)
if result_convert_video.returncode in [1, 2]:
raise OperationFailedError("Error can't convert the video")
for i in range(120):
time.sleep(1)
logger.info("Process video...")
if os.path.exists(OutputFile):
time.sleep(1)
command = "ffmpeg -y -i Video.mp4 -vn -acodec pcm_s16le -ar 44100 -ac 2 audio.wav"
result_convert_audio = subprocess.run(
command, capture_output=True, text=True, shell=True
)
time.sleep(1)
break
if i == 119:
# if not os.path.exists(OutputFile):
raise OperationFailedError("Error processing video")
if result_convert_audio.returncode in [1, 2]:
raise OperationFailedError(
f"Error can't create the audio file: {result_convert_audio.stderr}"
)
for i in range(120):
time.sleep(1)
logger.info("Process audio...")
if os.path.exists(audio_wav):
break
if i == 119:
raise OperationFailedError("Error can't create the audio file")
else:
video = video.strip()
if preview:
logger.warning(
"Creating a preview from the link, 10 "
"seconds to disable this option, go to "
"advanced settings and turn off preview."
)
# https://github.com/yt-dlp/yt-dlp/issues/2220
mp4_ = f'yt-dlp -f "mp4" --downloader ffmpeg --downloader-args "ffmpeg_i: -ss 00:00:20 -t 00:00:10" --force-overwrites --max-downloads 1 --no-warnings --no-abort-on-error --ignore-no-formats-error --restrict-filenames -o {OutputFile} {video}'
wav_ = "ffmpeg -y -i Video.mp4 -vn -acodec pcm_s16le -ar 44100 -ac 2 audio.wav"
result_convert_video = subprocess.run(
mp4_, capture_output=True, text=True, shell=True
)
result_convert_audio = subprocess.run(
wav_, capture_output=True, text=True, shell=True
)
if result_convert_audio.returncode in [1, 2]:
raise OperationFailedError("Error can't download a preview")
else:
mp4_ = f'yt-dlp -f "mp4" --force-overwrites --max-downloads 1 --no-warnings --no-abort-on-error --ignore-no-formats-error --restrict-filenames -o {OutputFile} {video}'
wav_ = f"python -m yt_dlp --output {audio_wav} --force-overwrites --max-downloads 1 --no-warnings --no-abort-on-error --ignore-no-formats-error --extract-audio --audio-format wav {video}"
result_convert_audio = subprocess.run(
wav_, capture_output=True, text=True, shell=True
)
if result_convert_audio.returncode in [1, 2]:
raise OperationFailedError("Error can't download the audio")
for i in range(120):
time.sleep(1)
logger.info("Process audio...")
if os.path.exists(audio_wav) and not os.path.exists(
"audio.webm"
):
time.sleep(1)
result_convert_video = subprocess.run(
mp4_, capture_output=True, text=True, shell=True
)
break
if i == 119:
raise OperationFailedError("Error downloading the audio")
if result_convert_video.returncode in [1, 2]:
raise OperationFailedError("Error can't download the video")