mirror of
https://github.com/DrewThomasson/ebook2audiobook.git
synced 2026-01-09 13:58:14 -05:00
remove DOCKER_UTILS
This commit is contained in:
@@ -1,53 +0,0 @@
|
||||
# Use a minimal Debian-based image with GNU libc 2.35 or later
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
# Set environment variables
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV LC_ALL=C.UTF-8
|
||||
ENV LANG=C.UTF-8
|
||||
ENV LANGUAGE=C.UTF-8
|
||||
ENV QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox"
|
||||
|
||||
# Install required dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
wget \
|
||||
xz-utils \
|
||||
python3 \
|
||||
python3-pip \
|
||||
ffmpeg \
|
||||
libegl1 \
|
||||
libopengl0 \
|
||||
libgl1-mesa-glx \
|
||||
libxcb-cursor0 \
|
||||
libxkbcommon0 \
|
||||
libxkbfile1 \
|
||||
libnss3 \
|
||||
libx11-6 \
|
||||
libxext6 \
|
||||
libxrender1 \
|
||||
libxtst6 \
|
||||
libxrandr2 \
|
||||
libxcomposite1 \
|
||||
qtbase5-dev \
|
||||
libqt5webenginecore5 \
|
||||
libqt5webenginewidgets5 \
|
||||
libqt5webchannel5 \
|
||||
libqt5websockets5 && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Calibre (specifically for CLI use like ebook-convert)
|
||||
RUN wget -nv -O- https://download.calibre-ebook.com/linux-installer.sh | sh /dev/stdin
|
||||
|
||||
# Add Calibre's CLI tools to PATH
|
||||
ENV PATH="/opt/calibre:${PATH}"
|
||||
|
||||
# Default working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Modified ENTRYPOINT to print the command and its arguments
|
||||
ENTRYPOINT ["/bin/sh", "-c", "echo 'Running command: $0 $@'; exec \"$0\" \"$@\""]
|
||||
|
||||
# CMD to pass arguments dynamically
|
||||
CMD ["sh", "-c"]
|
||||
|
||||
5
app.py
5
app.py
@@ -134,9 +134,8 @@ Linux/Mac:
|
||||
'--version', '--help'
|
||||
]
|
||||
all_group = parser.add_argument_group('**** The following options are for all modes', 'Optional')
|
||||
all_group.add_argument(options[0], type=str, help='''Mode the script will run. Accepted values are "native", "docker_utils", "full_docker".
|
||||
Default mode is "native". "docker_utils" use a docker for ffmpeg and calibre.
|
||||
"full_docker" cannot be used without a docker command.''')
|
||||
all_group.add_argument(options[0], type=str, help='''Mode the script will run. Accepted values are "native" and "full_docker". Default mode is "native".
|
||||
"full_docker" cannot be used without a docker command.''')
|
||||
parser.add_argument(options[1], type=str, help='''Session to resume the conversion in case of interruption, crash,
|
||||
or reuse of custom models and custom cloning voices.''')
|
||||
gui_group = parser.add_argument_group('**** The following option are for gradio/gui mode only', 'Optional')
|
||||
|
||||
@@ -5,14 +5,12 @@ setlocal enabledelayedexpansion
|
||||
set "ARGS=%*"
|
||||
|
||||
set "NATIVE=native"
|
||||
set "DOCKER_UTILS=docker_utils"
|
||||
set "FULL_DOCKER=full_docker"
|
||||
|
||||
set "SCRIPT_MODE=%NATIVE%"
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
|
||||
set "PYTHON_VERSION=3.12"
|
||||
set "DOCKER_UTILS_IMG=utils"
|
||||
set "PYTHON_ENV=python_env"
|
||||
set "CURRENT_ENV="
|
||||
set "PROGRAMS_LIST=calibre ffmpeg nodejs espeak-ng"
|
||||
@@ -30,7 +28,6 @@ set "PROGRAMS_CHECK=0"
|
||||
set "CONDA_CHECK_STATUS=0"
|
||||
set "CONDA_RUN_INIT=0"
|
||||
set "DOCKER_CHECK_STATUS=0"
|
||||
set "DOCKER_BUILD_STATUS=0"
|
||||
|
||||
set "HELP_FOUND=%ARGS:--help=%"
|
||||
|
||||
@@ -39,13 +36,6 @@ for /f "tokens=2,*" %%A in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Se
|
||||
set "PATH=%%B;%PATH%"
|
||||
)
|
||||
|
||||
for %%A in (%ARGS%) do (
|
||||
if "%%A"=="%DOCKER_UTILS%" (
|
||||
set "SCRIPT_MODE=%DOCKER_UTILS%"
|
||||
break
|
||||
)
|
||||
)
|
||||
|
||||
cd /d "%SCRIPT_DIR%"
|
||||
|
||||
:: Check if running inside Docker
|
||||
@@ -93,13 +83,8 @@ if not defined conda_version (
|
||||
echo This script runs with its own virtual env and must be out of any other virtual environment when it's launched.
|
||||
goto failed
|
||||
)
|
||||
if "%SCRIPT_MODE%"=="%DOCKER_UTILS%" (
|
||||
goto docker_check
|
||||
exit /b
|
||||
) else (
|
||||
call :programs_check
|
||||
exit /b
|
||||
)
|
||||
call :programs_check
|
||||
exit /b
|
||||
)
|
||||
goto dispatch
|
||||
exit /b
|
||||
@@ -133,26 +118,8 @@ if %errorlevel% neq 0 (
|
||||
if %errorlevel% neq 0 (
|
||||
set "DOCKER_CHECK_STATUS=1"
|
||||
) else (
|
||||
:: Check if the Docker socket is running
|
||||
set "docker_socket="
|
||||
if exist \\.\pipe\docker_engine (
|
||||
set "docker_socket=Windows"
|
||||
)
|
||||
if not defined docker_socket (
|
||||
echo Cannot connect to docker socket. Check if the docker socket is running.
|
||||
goto failed
|
||||
exit /b
|
||||
) else (
|
||||
:: Check if the Docker image is available
|
||||
call docker images -q %DOCKER_UTILS_IMG% >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo Docker image '%DOCKER_UTILS_IMG%' not found. Installing it now...
|
||||
set "DOCKER_BUILD_STATUS=1"
|
||||
) else (
|
||||
goto dispatch
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
goto dispatch
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
goto install_components
|
||||
@@ -211,17 +178,6 @@ if not "%DOCKER_CHECK_STATUS%"=="0" (
|
||||
)
|
||||
)
|
||||
)
|
||||
:: Build Docker image if required
|
||||
if not "%DOCKER_BUILD_STATUS%"=="0" (
|
||||
call conda activate "%SCRIPT_DIR%\%PYTHON_ENV%"
|
||||
call python -m pip install -e .
|
||||
call docker build -f DockerfileUtils -t utils .
|
||||
call conda deactivate
|
||||
call docker images -q %DOCKER_UTILS_IMG% >nul 2>&1
|
||||
if %errorlevel% equ 0 (
|
||||
set "DOCKER_BUILD_STATUS=0"
|
||||
)
|
||||
)
|
||||
goto dispatch
|
||||
exit /b
|
||||
|
||||
@@ -229,10 +185,8 @@ exit /b
|
||||
if "%PROGRAMS_CHECK%"=="0" (
|
||||
if "%CONDA_CHECK_STATUS%"=="0" (
|
||||
if "%DOCKER_CHECK_STATUS%"=="0" (
|
||||
if "%DOCKER_BUILD_STATUS%"=="0" (
|
||||
goto main
|
||||
exit /b
|
||||
)
|
||||
goto main
|
||||
exit /b
|
||||
) else (
|
||||
goto failed
|
||||
exit /b
|
||||
@@ -242,7 +196,6 @@ if "%PROGRAMS_CHECK%"=="0" (
|
||||
echo PROGRAMS_CHECK: %PROGRAMS_CHECK%
|
||||
echo CONDA_CHECK_STATUS: %CONDA_CHECK_STATUS%
|
||||
echo DOCKER_CHECK_STATUS: %DOCKER_CHECK_STATUS%
|
||||
echo DOCKER_BUILD_STATUS: %DOCKER_BUILD_STATUS%
|
||||
timeout /t 5 /nobreak >nul
|
||||
goto install_components
|
||||
exit /b
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ -z "$SWITCHED_TO_ZSH" && "$SHELL" = */bin/zsh ]]; then
|
||||
if [[ -z "$SWITCHED_TO_ZSH" && "$SHELL" = */zsh ]]; then
|
||||
SWITCHED_TO_ZSH=1 exec env zsh "$0" "$@"
|
||||
fi
|
||||
|
||||
@@ -35,7 +35,6 @@ while [[ "$#" -gt 0 ]]; do
|
||||
done
|
||||
|
||||
NATIVE="native"
|
||||
DOCKER_UTILS="docker_utils"
|
||||
FULL_DOCKER="full_docker"
|
||||
|
||||
SCRIPT_MODE="$NATIVE"
|
||||
@@ -45,7 +44,6 @@ TMPDIR=./.cache
|
||||
|
||||
WGET=$(which wget 2>/dev/null)
|
||||
REQUIRED_PROGRAMS=("calibre" "ffmpeg" "mecab" "nodejs" "espeak" "espeak-ng" "rustc" "cargo")
|
||||
DOCKER_UTILS_IMG="utils"
|
||||
PYTHON_ENV="python_env"
|
||||
CURRENT_ENV=""
|
||||
|
||||
@@ -90,7 +88,7 @@ if [[ -n "$container" || -f /.dockerenv ]]; then
|
||||
SCRIPT_MODE="$FULL_DOCKER"
|
||||
else
|
||||
if [[ -n "${arguments['script_mode']+exists}" ]]; then
|
||||
if [ "${arguments['script_mode']}" = "$NATIVE" ] || [ "${arguments['script_mode']}" = "$DOCKER_UTILS" ]; then
|
||||
if [ "${arguments['script_mode']}" = "$NATIVE" ]; then
|
||||
SCRIPT_MODE="${arguments['script_mode']}"
|
||||
fi
|
||||
fi
|
||||
@@ -244,9 +242,6 @@ else
|
||||
done
|
||||
if required_programs_check "${REQUIRED_PROGRAMS[@]}"; then
|
||||
return 0
|
||||
else
|
||||
echo -e "\e[33mYou can run 'ebook2audiobook.sh --script_mode docker_utils' to avoid to install $REQUIRED_PROGRAMS natively.\e[0m"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -302,35 +297,14 @@ else
|
||||
rm -f get-docker.sh
|
||||
fi
|
||||
echo -e "\e[32m===============>>> docker is installed! <<===============\e[0m"
|
||||
docker_build
|
||||
else
|
||||
# Check if Docker service is running
|
||||
if docker info >/dev/null 2>&1; then
|
||||
if [[ "$(docker images -q $DOCKER_UTILS_IMG 2> /dev/null)" = "" ]]; then
|
||||
docker_build
|
||||
fi
|
||||
else
|
||||
echo -e "\e[33mDocker is not running\e[0m"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
function docker_build {
|
||||
# Check if the Docker socket is accessible
|
||||
if [[ -e /var/run/docker.sock || -e /run/docker.sock ]]; then
|
||||
echo -e "\e[33mDocker image '$DOCKER_UTILS_IMG' not found. Trying to build it...\e[0m"
|
||||
docker build -f DockerfileUtils -t utils .
|
||||
else
|
||||
echo -e "\e[33mcannot connect to docker socket. Check if the docker socket is running.\e[0m"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$SCRIPT_MODE" = "$FULL_DOCKER" ]; then
|
||||
echo -e "\e[33mRunning in $FULL_DOCKER mode\e[0m"
|
||||
python app.py --script_mode "$SCRIPT_MODE" "${ARGS[@]}"
|
||||
elif [[ "$SCRIPT_MODE" = "$NATIVE" || "$SCRIPT_MODE" = "$DOCKER_UTILS" ]]; then
|
||||
elif [ "$SCRIPT_MODE" = "$NATIVE" ]; then
|
||||
pass=true
|
||||
echo -e "\e[33mRunning in $SCRIPT_MODE mode\e[0m"
|
||||
if [ "$SCRIPT_MODE" = "$NATIVE" ]; then
|
||||
|
||||
@@ -13,19 +13,19 @@ from lib.models import models
|
||||
|
||||
class VoiceExtractor:
|
||||
|
||||
def __init__(self, session, models_dir, input_file, voice_name):
|
||||
def __init__(self, session, models_dir, voice_file, voice_name):
|
||||
self.wav_file = None
|
||||
self.session = session
|
||||
self.input_file = input_file
|
||||
self.voice_file = voice_file
|
||||
self.voice_name = voice_name
|
||||
self.models_dir = models_dir
|
||||
self.voice_track = 'vocals.wav'
|
||||
self.samplerate = models[session['tts_engine']][session['fine_tuned']]['samplerate']
|
||||
self.output_dir = self.session['voice_dir']
|
||||
self.demucs_dir = os.path.join(self.output_dir, 'htdemucs', os.path.splitext(os.path.basename(self.input_file))[0])
|
||||
self.demucs_dir = os.path.join(self.output_dir, 'htdemucs', os.path.splitext(os.path.basename(self.voice_file))[0])
|
||||
|
||||
def _validate_format(self):
|
||||
file_extension = os.path.splitext(self.input_file)[1].lower()
|
||||
file_extension = os.path.splitext(self.voice_file)[1].lower()
|
||||
if file_extension in voice_formats:
|
||||
msg = 'Input file valid'
|
||||
return True, msg
|
||||
@@ -34,18 +34,14 @@ class VoiceExtractor:
|
||||
|
||||
def _convert_to_wav(self):
|
||||
try:
|
||||
if not self.input_file.lower().endswith(f'_{self.samplerate}.wav'):
|
||||
self.wav_file = os.path.join(os.path.dirname(self.input_file), os.path.basename(self.input_file).replace(os.path.splitext(self.input_file)[1], '.wav'))
|
||||
process = (
|
||||
ffmpeg
|
||||
.input(self.input_file)
|
||||
.output(self.wav_file, format='wav', ar=self.samplerate, ac=1)
|
||||
.run(overwrite_output=True)
|
||||
)
|
||||
msg = 'Conversion to .wav format for processing successful'
|
||||
else:
|
||||
self.wav_file = self.input_file
|
||||
msg = 'File is already a .wav format'
|
||||
self.wav_file = os.path.join(self.session['voice_dir'], os.path.basename(self.voice_file).replace(os.path.splitext(self.voice_file)[1], '.wav'))
|
||||
process = (
|
||||
ffmpeg
|
||||
.input(self.voice_file)
|
||||
.output(self.wav_file, format='wav', ar=self.samplerate, ac=1)
|
||||
.run(overwrite_output=True)
|
||||
)
|
||||
msg = 'Conversion to .wav format for processing successful'
|
||||
return True, msg
|
||||
except ffmpeg.Error as e:
|
||||
error = f'convert_to_wav fmpeg.Error: {e.stderr.decode()}'
|
||||
|
||||
@@ -6,7 +6,6 @@ min_python_version = (3,12)
|
||||
max_python_version = (3,12)
|
||||
|
||||
NATIVE = 'native'
|
||||
DOCKER_UTILS = 'docker_utils'
|
||||
FULL_DOCKER = 'full_docker'
|
||||
|
||||
debug_mode = True
|
||||
@@ -16,7 +15,6 @@ default_device = "cuda"
|
||||
|
||||
python_env_dir = os.path.abspath(os.path.join('.','python_env'))
|
||||
requirements_file = os.path.abspath(os.path.join('.','requirements.txt'))
|
||||
docker_utils_image = 'utils'
|
||||
|
||||
interface_host = '0.0.0.0'
|
||||
interface_port = 7860
|
||||
|
||||
269
lib/functions.py
269
lib/functions.py
@@ -428,72 +428,32 @@ def convert_to_epub(session):
|
||||
if session['cancellation_requested']:
|
||||
print('Cancel requested')
|
||||
return False
|
||||
|
||||
if session['script_mode'] == DOCKER_UTILS:
|
||||
try:
|
||||
docker_dir = os.path.basename(session['process_dir'])
|
||||
docker_file_in = os.path.basename(session['ebook'])
|
||||
docker_file_out = os.path.basename(session['epub_path'])
|
||||
|
||||
# Check if the input file is already an EPUB
|
||||
if docker_file_in.lower().endswith('.epub'):
|
||||
shutil.copy(session['ebook'], session['epub_path'])
|
||||
print("File is already in EPUB format. Copying directly.")
|
||||
return True
|
||||
|
||||
# Convert using Docker
|
||||
print(f"Starting Docker container to convert {docker_file_in} to EPUB.")
|
||||
container_logs = session['client'].containers.run(
|
||||
docker_utils_image,
|
||||
command=f'ebook-convert /files/{docker_dir}/{docker_file_in} /files/{docker_dir}/{docker_file_out} --input-encoding=utf-8 --output-profile=generic_eink --verbose',
|
||||
volumes={session['process_dir']: {'bind': f'/files/{docker_dir}', 'mode': 'rw'}},
|
||||
remove=True,
|
||||
detach=False,
|
||||
stdout=True,
|
||||
stderr=True
|
||||
)
|
||||
print(container_logs.decode('utf-8'))
|
||||
return True
|
||||
|
||||
except docker.errors.ContainerError as e:
|
||||
print(f"Docker container error: {e}")
|
||||
DependencyError(e)
|
||||
try:
|
||||
util_app = shutil.which('ebook-convert')
|
||||
if not util_app:
|
||||
error = "The 'ebook-convert' utility is not installed or not found."
|
||||
print(error)
|
||||
return False
|
||||
except docker.errors.ImageNotFound as e:
|
||||
print(f"Docker image not found: {e}")
|
||||
DependencyError(e)
|
||||
return False
|
||||
except docker.errors.APIError as e:
|
||||
print(f"Docker API error: {e}")
|
||||
DependencyError(e)
|
||||
return False
|
||||
else:
|
||||
try:
|
||||
util_app = shutil.which('ebook-convert')
|
||||
if not util_app:
|
||||
error = "The 'ebook-convert' utility is not installed or not found."
|
||||
print(error)
|
||||
return False
|
||||
print(f"Running command: {util_app} {session['ebook']} {session['epub_path']} --input-encoding=utf-8 --output-profile=generic_eink --verbose")
|
||||
result = subprocess.run(
|
||||
[util_app, session['ebook'], session['epub_path'], '--input-encoding=utf-8', '--output-profile=generic_eink', '--verbose'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
universal_newlines=True,
|
||||
encoding='utf-8'
|
||||
)
|
||||
print(result.stdout)
|
||||
return True
|
||||
print(f"Running command: {util_app} {session['ebook']} {session['epub_path']} --input-encoding=utf-8 --output-profile=generic_eink --verbose")
|
||||
result = subprocess.run(
|
||||
[util_app, session['ebook'], session['epub_path'], '--input-encoding=utf-8', '--output-profile=generic_eink', '--verbose'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
universal_newlines=True,
|
||||
encoding='utf-8'
|
||||
)
|
||||
print(result.stdout)
|
||||
return True
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Subprocess error: {e.stderr}")
|
||||
DependencyError(e)
|
||||
return False
|
||||
except FileNotFoundError as e:
|
||||
print(f"Utility not found: {e}")
|
||||
DependencyError(e)
|
||||
return False
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Subprocess error: {e.stderr}")
|
||||
DependencyError(e)
|
||||
return False
|
||||
except FileNotFoundError as e:
|
||||
print(f"Utility not found: {e}")
|
||||
DependencyError(e)
|
||||
return False
|
||||
|
||||
def get_cover(epubBook, session):
|
||||
try:
|
||||
@@ -655,101 +615,6 @@ def get_sanitized(str, replacement="_"):
|
||||
sanitized = sanitized.strip()
|
||||
return sanitized
|
||||
|
||||
def normalize_voice_file(f, session):
|
||||
if re.search(r'_(16000|24000)\.wav$', f):
|
||||
return f
|
||||
else:
|
||||
final_name = os.path.splitext(os.path.basename(f))[0].replace('&', 'And').replace(' ', '_') + '.wav'
|
||||
final_name = get_sanitized(final_name)
|
||||
final_file = os.path.join(session['voice_dir'], final_name)
|
||||
if session['script_mode'] == DOCKER_UTILS:
|
||||
docker_dir = os.path.basename(session['voice_dir'])
|
||||
ffmpeg_input_file = f'/files/{docker_dir}/' + os.path.basename(f)
|
||||
ffmpeg_final_file = f'/files/{docker_dir}/' + os.path.basename(final_file)
|
||||
ffmpeg_cmd = ['ffmpeg', '-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda', '-i', ffmpeg_input_file]
|
||||
else:
|
||||
ffmpeg_input_file = f
|
||||
ffmpeg_final_file = final_file
|
||||
ffmpeg_cmd = [shutil.which('ffmpeg'), '-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda', '-i', ffmpeg_input_file]
|
||||
ffmpeg_cmd += [
|
||||
'-strict', 'experimental',
|
||||
'-filter_complex', '[0:a]'
|
||||
'agate=threshold=-25dB:ratio=1.4:attack=10:release=250,'
|
||||
'afftdn=nf=-70,'
|
||||
'acompressor=threshold=-20dB:ratio=2:attack=80:release=200:makeup=1dB,'
|
||||
'loudnorm=I=-14:TP=-3:LRA=7:linear=true,'
|
||||
'equalizer=f=150:t=q:w=2:g=1,'
|
||||
'equalizer=f=250:t=q:w=2:g=-3,'
|
||||
'equalizer=f=3000:t=q:w=2:g=2,'
|
||||
'equalizer=f=5500:t=q:w=2:g=-4,'
|
||||
'equalizer=f=9000:t=q:w=2:g=-2,'
|
||||
'highpass=f=63,'
|
||||
'pan=mono|c0=0.5*FL+0.5*FR[audio]',
|
||||
'-map', '[audio]',
|
||||
'-ar', '16000',
|
||||
'-y', ffmpeg_final_file
|
||||
]
|
||||
error = None
|
||||
for rate in ['16000', '24000']:
|
||||
ffmpeg_cmd[-3] = str(rate)
|
||||
ffmpeg_cmd[-1] = final_file.replace('.wav', f'_{rate}.wav')
|
||||
if session['script_mode'] == DOCKER_UTILS:
|
||||
try:
|
||||
container = session['client'].containers.run(
|
||||
docker_utils_image,
|
||||
command=ffmpeg_cmd,
|
||||
volumes={session['voice_dir']: {'bind': f'/files/{docker_dir}', 'mode': 'rw'}},
|
||||
remove=True,
|
||||
detach=False,
|
||||
stdout=True,
|
||||
stderr=True
|
||||
)
|
||||
print(container.decode('utf-8', errors='replace'))
|
||||
if not shutil.copy(docker_final_file, final_file):
|
||||
error = f'Could not copy from {docker_final_file} to {final_file}'
|
||||
except docker.errors.ContainerError as e:
|
||||
error = f"normalize_voice_file() error: {e}"
|
||||
pass
|
||||
break
|
||||
except docker.errors.ImageNotFound as e:
|
||||
error = f"normalize_voice_file() error: {e}"
|
||||
pass
|
||||
break
|
||||
except docker.errors.APIError as e:
|
||||
error = f"normalize_voice_file() error: {e}"
|
||||
pass
|
||||
break
|
||||
else:
|
||||
try:
|
||||
process = subprocess.Popen(
|
||||
ffmpeg_cmd,
|
||||
env={},
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
text=True,
|
||||
universal_newlines=True,
|
||||
encoding='utf-8'
|
||||
)
|
||||
for line in process.stdout:
|
||||
print(line, end='') # Print each line of stdout
|
||||
process.wait()
|
||||
if process.returncode != 0:
|
||||
error = f'normalize_voice_file(): process.returncode: {process.returncode}'
|
||||
break
|
||||
except subprocess.CalledProcessError as e:
|
||||
error = f"normalize_voice_file() error: {e}"
|
||||
pass
|
||||
break
|
||||
except Exception as e:
|
||||
error = f"normalize_voice_file() error: {e}"
|
||||
pass
|
||||
break
|
||||
if error is not None:
|
||||
print(error)
|
||||
return None
|
||||
else:
|
||||
return final_file.replace('.wav','_24000.wav')
|
||||
|
||||
def convert_chapters_to_audio(session):
|
||||
try:
|
||||
if session['cancellation_requested']:
|
||||
@@ -940,21 +805,12 @@ def combine_audio_chapters(session):
|
||||
print('Cancel requested')
|
||||
return False
|
||||
ffmpeg_cover = None
|
||||
if session['script_mode'] == DOCKER_UTILS:
|
||||
docker_dir = os.path.basename(session['process_dir'])
|
||||
ffmpeg_combined_audio = f'/files/{docker_dir}/' + os.path.basename(combined_chapters_file)
|
||||
ffmpeg_metadata_file = f'/files/{docker_dir}/' + os.path.basename(metadata_file)
|
||||
ffmpeg_final_file = f'/files/{docker_dir}/' + os.path.basename(docker_final_file)
|
||||
if session['cover'] is not None:
|
||||
ffmpeg_cover = f'/files/{docker_dir}/' + os.path.basename(session['cover'])
|
||||
ffmpeg_cmd = ['ffmpeg', '-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda', '-i', ffmpeg_combined_audio, '-i', ffmpeg_metadata_file]
|
||||
else:
|
||||
ffmpeg_combined_audio = combined_chapters_file
|
||||
ffmpeg_metadata_file = metadata_file
|
||||
ffmpeg_final_file = final_file
|
||||
if session['cover'] is not None:
|
||||
ffmpeg_cover = session['cover']
|
||||
ffmpeg_cmd = [shutil.which('ffmpeg'), '-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda', '-i', ffmpeg_combined_audio, '-i', ffmpeg_metadata_file]
|
||||
ffmpeg_combined_audio = combined_chapters_file
|
||||
ffmpeg_metadata_file = metadata_file
|
||||
ffmpeg_final_file = final_file
|
||||
if session['cover'] is not None:
|
||||
ffmpeg_cover = session['cover']
|
||||
ffmpeg_cmd = [shutil.which('ffmpeg'), '-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda', '-i', ffmpeg_combined_audio, '-i', ffmpeg_metadata_file]
|
||||
if session['output_format'] == 'wav':
|
||||
ffmpeg_cmd += ['-map', '0:a']
|
||||
elif session['output_format'] == 'aac':
|
||||
@@ -997,51 +853,26 @@ def combine_audio_chapters(session):
|
||||
ffmpeg_cmd += ['-af', 'afftdn=nf=-70']
|
||||
ffmpeg_cmd += ['-strict', 'experimental', '-map_metadata', '1']
|
||||
ffmpeg_cmd += ['-threads', '8', '-y', ffmpeg_final_file]
|
||||
if session['script_mode'] == DOCKER_UTILS:
|
||||
try:
|
||||
container = session['client'].containers.run(
|
||||
docker_utils_image,
|
||||
command=ffmpeg_cmd,
|
||||
volumes={session['process_dir']: {'bind': f'/files/{docker_dir}', 'mode': 'rw'}},
|
||||
remove=True,
|
||||
detach=False,
|
||||
stdout=True,
|
||||
stderr=True
|
||||
)
|
||||
print(container.decode('utf-8', errors='replace'))
|
||||
if shutil.copy(docker_final_file, final_file):
|
||||
return True
|
||||
return False
|
||||
except docker.errors.ContainerError as e:
|
||||
DependencyError(e)
|
||||
return False
|
||||
except docker.errors.ImageNotFound as e:
|
||||
DependencyError(e)
|
||||
return False
|
||||
except docker.errors.APIError as e:
|
||||
DependencyError(e)
|
||||
return False
|
||||
else:
|
||||
try:
|
||||
process = subprocess.Popen(
|
||||
ffmpeg_cmd,
|
||||
env={},
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
encoding='utf-8'
|
||||
)
|
||||
for line in process.stdout:
|
||||
print(line, end='') # Print each line of stdout
|
||||
process.wait()
|
||||
if process.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
error = process.returncode
|
||||
print(error, ffmpeg_cmd)
|
||||
return False
|
||||
except subprocess.CalledProcessError as e:
|
||||
DependencyError(e)
|
||||
try:
|
||||
process = subprocess.Popen(
|
||||
ffmpeg_cmd,
|
||||
env={},
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
encoding='utf-8'
|
||||
)
|
||||
for line in process.stdout:
|
||||
print(line, end='') # Print each line of stdout
|
||||
process.wait()
|
||||
if process.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
error = process.returncode
|
||||
print(error, ffmpeg_cmd)
|
||||
return False
|
||||
except subprocess.CalledProcessError as e:
|
||||
DependencyError(e)
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
DependencyError(e)
|
||||
@@ -1276,8 +1107,6 @@ def convert_ebook(args):
|
||||
bool, e = check_programs('FFmpeg', 'ffmpeg', '-version')
|
||||
if not bool:
|
||||
error = f'check_programs() FFMPEG failed: {e}'
|
||||
elif session['script_mode'] == DOCKER_UTILS:
|
||||
session['client'] = docker.from_env()
|
||||
|
||||
if error is None:
|
||||
session['session_dir'] = os.path.join(tmp_dir, f"ebook-{session['id']}")
|
||||
|
||||
Reference in New Issue
Block a user