diff --git a/encode_video.py b/encode_video.py index b1ef79c..6ecabc7 100755 --- a/encode_video.py +++ b/encode_video.py @@ -19,10 +19,12 @@ def encode(input_file, codec): ffmpeg_codec = "libx265" crf = 26 folder = "h265" + extra_params = ["-crf", str(crf)] elif codec == "av1": - ffmpeg_codec = "libaom-av1" - crf = 32 + ffmpeg_codec = "av1_nvenc" + cq = 32 folder = "av1" + extra_params = ["-pix_fmt", "yuv420p", "-preset", "p4", "-cq", str(cq), "-rc", "vbr", "-b:v", "0"] else: raise ValueError("Unsupported codec") @@ -37,36 +39,49 @@ def encode(input_file, codec): outdir = os.path.join(os.path.dirname(input_file), folder) os.makedirs(outdir, exist_ok=True) output_file = os.path.join(outdir, f"{name}.mkv") + log_file = os.path.join(outdir, f"{name}.log") cmd = [ "ffmpeg", "-i", input_file, "-map", "0", + ] + extra_params + [ "-c:v", ffmpeg_codec, - "-crf", str(crf), "-c:a", "copy", "-c:s", "copy", "-y", output_file ] print(f"\n🎬 Encoding {filename} → {folder}/{name}.mkv") - process = subprocess.Popen(cmd, stderr=subprocess.PIPE, text=True) + with open(log_file, "w") as log: + process = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True) - time_re = re.compile(r"time=(\d+):(\d+):([\d.]+)") - last_percent = -1 + time_re = re.compile(r"time=(\d+):(\d+):([\d.]+)") + last_percent = -1 - for line in process.stderr: - match = time_re.search(line) - if match: - h, m, s = map(float, match.groups()) - current = h * 3600 + m * 60 + s - percent = int((current / duration) * 100) - if percent != last_percent: - print(f"\r⏳ Progress: {percent}%", end='', flush=True) - last_percent = percent + while True: + line = process.stderr.readline() + if not line: + break + log.write(line) + match = time_re.search(line) + if match: + h, m, s = map(float, match.groups()) + current = h * 3600 + m * 60 + s + percent = int((current / duration) * 100) + if percent != last_percent: + print(f"\r⏳ Progress: {percent}%", end='', flush=True) + last_percent = percent - process.wait() - print("\n✅ Done.") + process.wait() + + if process.returncode != 0: + print(f"\n❌ [Error] FFmpeg failed for {filename}. Check the log: {log_file}") + # Clean broken output + if os.path.exists(output_file): + os.remove(output_file) + else: + print("\n✅ Done.") def encode_batch(directory, codec): if not os.path.isdir(directory): @@ -77,10 +92,14 @@ def encode_batch(directory, codec): for file in files: if file.lower().endswith(SUPPORTED_EXTENSIONS): filepath = os.path.join(root, file) - encode(filepath, codec) + try: + encode(filepath, codec) + except Exception as e: + print(f"\n❌ Error with file {file}: {e}") + continue def main(): - parser = argparse.ArgumentParser(description="Encode video(s) to x265 or AV1.") + parser = argparse.ArgumentParser(description="Encode video(s) to x265 or AV1 with GPU.") parser.add_argument("input", nargs="?", help="Path to input file") parser.add_argument("-d", "--directory", help="Path to a directory for batch encoding") parser.add_argument("--codec", choices=["x265", "av1"], default="x265", help="Codec to use (default: x265)") @@ -99,4 +118,3 @@ def main(): if __name__ == "__main__": main() -