Make progress bar show continous progress
This commit is contained in:
parent
ae7ff3210c
commit
27dd9da6a6
1 changed files with 57 additions and 20 deletions
|
@ -1,23 +1,12 @@
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
from gi.repository import GLib
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import re
|
||||||
def transcode_file(input_path, output_dir):
|
from gi.repository import GLib
|
||||||
os.makedirs(output_dir, exist_ok=True)
|
|
||||||
basename = os.path.basename(input_path)
|
|
||||||
output_path = os.path.join(output_dir, basename)
|
|
||||||
|
|
||||||
cmd = [
|
|
||||||
"ffmpeg", "-y", "-i", input_path,
|
|
||||||
"-c:v", "libx264", "-preset", "fast",
|
|
||||||
"-c:a", "aac", output_path
|
|
||||||
]
|
|
||||||
|
|
||||||
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
return result.returncode == 0, output_path
|
|
||||||
|
|
||||||
class TranscoderWorker:
|
class TranscoderWorker:
|
||||||
|
TIME_RE = re.compile(r"time=(\d+):(\d+):(\d+)\.(\d+)")
|
||||||
|
|
||||||
def __init__(self, files, progress_callback=None, done_callback=None):
|
def __init__(self, files, progress_callback=None, done_callback=None):
|
||||||
self.files = files
|
self.files = files
|
||||||
self.progress_callback = progress_callback
|
self.progress_callback = progress_callback
|
||||||
|
@ -34,20 +23,68 @@ class TranscoderWorker:
|
||||||
|
|
||||||
def _process_files(self):
|
def _process_files(self):
|
||||||
total = len(self.files)
|
total = len(self.files)
|
||||||
for idx, filepath in enumerate(self.files):
|
for idx, filepath in enumerate(self.files, start=1):
|
||||||
basename = os.path.basename(filepath)
|
basename = os.path.basename(filepath)
|
||||||
self._update_progress(f"Processing {basename} ({idx}/{total})...", idx / total)
|
self._update_progress(f"Starting {basename}", (idx - 1) / total)
|
||||||
|
|
||||||
success, output_path = transcode_file(filepath, os.path.join(os.path.dirname(filepath), "transcoded"))
|
success, output_path = self._transcode_file(filepath, os.path.join(os.path.dirname(filepath), "transcoded"), basename, idx, total)
|
||||||
if not success:
|
if not success:
|
||||||
self._update_progress(f"Error transcoding {basename}", idx + 1 / total)
|
self._update_progress(f"Error transcoding {basename}", idx / total)
|
||||||
else:
|
else:
|
||||||
self._update_progress(f"Finished {basename}", idx + 1 / total)
|
self._update_progress(f"Finished {basename}", idx / total)
|
||||||
|
|
||||||
self.is_processing = False
|
self.is_processing = False
|
||||||
self._update_progress("All done!", 1.0)
|
self._update_progress("All done!", 1.0)
|
||||||
self._notify_done()
|
self._notify_done()
|
||||||
|
|
||||||
|
def _transcode_file(self, input_path, output_dir, basename, idx, total):
|
||||||
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
|
output_path = os.path.join(output_dir, basename)
|
||||||
|
|
||||||
|
# Get duration of input file
|
||||||
|
duration = self._get_duration(input_path)
|
||||||
|
if duration is None:
|
||||||
|
duration = 1.0 # fallback to avoid division by zero
|
||||||
|
|
||||||
|
cmd = [
|
||||||
|
"ffmpeg", "-y", "-i", input_path,
|
||||||
|
"-c:v", "libx264", "-preset", "fast",
|
||||||
|
"-c:a", "aac", output_path
|
||||||
|
]
|
||||||
|
|
||||||
|
process = subprocess.Popen(cmd, stderr=subprocess.PIPE, universal_newlines=True)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
line = process.stderr.readline()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
|
||||||
|
match = self.TIME_RE.search(line)
|
||||||
|
if match:
|
||||||
|
hours, minutes, seconds, milliseconds = map(int, match.groups())
|
||||||
|
elapsed = hours * 3600 + minutes * 60 + seconds + milliseconds / 100
|
||||||
|
progress_fraction = min(elapsed / duration, 1.0)
|
||||||
|
overall_fraction = (idx - 1 + progress_fraction) / total
|
||||||
|
self._update_progress(f"Transcoding {basename}", overall_fraction)
|
||||||
|
|
||||||
|
process.wait()
|
||||||
|
success = (process.returncode == 0)
|
||||||
|
return success, output_path
|
||||||
|
|
||||||
|
def _get_duration(self, input_path):
|
||||||
|
# Run ffprobe to get duration in seconds
|
||||||
|
cmd = [
|
||||||
|
"ffprobe", "-v", "error",
|
||||||
|
"-show_entries", "format=duration",
|
||||||
|
"-of", "default=noprint_wrappers=1:nokey=1",
|
||||||
|
input_path
|
||||||
|
]
|
||||||
|
try:
|
||||||
|
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
return float(output.strip())
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
def _update_progress(self, text, fraction):
|
def _update_progress(self, text, fraction):
|
||||||
if self.progress_callback:
|
if self.progress_callback:
|
||||||
GLib.idle_add(self.progress_callback, text, fraction)
|
GLib.idle_add(self.progress_callback, text, fraction)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue