Spaces:
Running
Running
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") | |