small fix and encoder update to db

main
oscar 2 months ago
parent c79ec8e179
commit 4596d9168f

1
.gitignore vendored

@ -181,3 +181,4 @@ cython_debug/
.cursorindexingignore
/failed
/static/thumbnails
/.temp

@ -45,7 +45,7 @@ def mark_missing_videos(cursor, conn):
conn.commit()
def fill_missing_filepaths(cursor, conn):
cursor.execute("SELECT id, filepath, status FROM videos")
cursor.execute("SELECT id, filepath, status, video_id FROM videos")
videos = cursor.fetchall()
with tqdm(videos, desc="Updating filepaths...") as pbar:
@ -54,8 +54,10 @@ def fill_missing_filepaths(cursor, conn):
filepath = vid['filepath']
if not filepath:
continue
filename = os.path.basename(filepath)
filename = f'{vid["video_id"]}.mp4'
else:
filename = os.path.basename(filepath)
status = vid['status']
path = find_video_path(filename)

@ -1,11 +1,8 @@
import os, shutil
import os, shutil, config
import ffmpeg
from tqdm import tqdm
def is_av1(filepath):
"""
Check if a video file is already AV1-encoded.
"""
try:
probe = ffmpeg.probe(filepath)
for stream in probe['streams']:
@ -17,10 +14,6 @@ def is_av1(filepath):
return False
def get_video_info(filepath):
"""
Returns (bitrate_in_kbps, (width, height)) for the specified video file.
If probing fails, returns (None, (None, None)).
"""
try:
probe = ffmpeg.probe(filepath)
format_info = probe['format']
@ -39,10 +32,6 @@ def get_video_info(filepath):
return None, (None, None)
def get_files(folder):
"""
Recursively gather all .mp4 files in `folder`.
Sort them by file size (smallest to largest) just as an example sorting.
"""
all_files = []
for root, _, filenames in os.walk(folder):
for filename in filenames:
@ -51,16 +40,7 @@ def get_files(folder):
all_files.append(os.path.join(root, filename))
return sorted(all_files, key=os.path.getsize)
def parse_text_for_print(text):
"""
If string is longer than 100 characters, only print the first 100 characters.
"""
return text[:100] + '...' if len(text) > 100 else text
def get_target_bitrate(width, height):
"""
Your existing function to choose a bitrate based on resolution.
"""
resolutions = {
(854, 480): 1000,
(1280, 720): 1500,
@ -76,7 +56,6 @@ def get_target_bitrate(width, height):
return 2500
def get_fps(filepath):
"""Get the frames per second (FPS) of the input video."""
try:
probe = ffmpeg.probe(filepath)
video_stream = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
@ -90,15 +69,11 @@ def get_fps(filepath):
return None
def encode_video(filepath, output_path, target_bitrate):
"""
Encode video using ffmpeg with a target bitrate (in kbps).
Using NVIDIA AV1 hardware encoder (av1_nvenc) for RTX 40-series.
"""
try:
fps = get_fps(filepath)
if fps is None:
print(f"Could not determine FPS for {filepath}, using default keyframe interval.")
fps = 30 # Default fallback if FPS can't be determined
print(f"Could not determine FPS for {filepath}.")
return False
keyframe_interval = int(fps) # Set the keyframe interval to match 1 second
@ -123,18 +98,12 @@ def encode_video(filepath, output_path, target_bitrate):
overwrite_output=True,
)
)
filepath_print = parse_text_for_print(filepath)
print(f" Finished encoding {filepath_print} to AV1 at {target_bitrate} kbps "
print(f" Finished encoding {os.path.basename(filepath)} to AV1 at {target_bitrate} kbps "
f"(maxrate={max_bitrate} kbps).")
except ffmpeg.Error as e:
filepath_print = parse_text_for_print(filepath)
print(f" Error encoding {filepath_print} to AV1: {e}")
print(f" Error encoding {os.path.basename(filepath)} to AV1: {e}")
def check_and_replace_if_smaller(original_path, temp_output_path):
"""
Compare file sizes and replace the original if the new one is smaller.
Otherwise, delete the temporary file.
"""
if not os.path.exists(temp_output_path):
print(f"[ERROR] Temp file {temp_output_path} not found. Skipping replacement...")
return
@ -162,19 +131,27 @@ def check_and_replace_if_smaller(original_path, temp_output_path):
shutil.move(temp_output_path, original_path)
return True
def reencode_videos_av1(input_folder):
"""
Main loop:
1. Gather .mp4 files
2. For each file, check if it's AV1 or if it needs re-encoding based on target bitrate.
3. Re-encode if needed.
4. Compare file sizes and replace if smaller.
"""
files = get_files(input_folder)
for input_path in tqdm(files, desc="Processing videos", unit="file"):
short_name = parse_text_for_print(input_path)
def update_codec_db(video_id, codec):
conn, cursor = config.get_local_db_connection()
cursor.execute("UPDATE videos SET codec = %s WHERE id = %s", (codec, video_id))
conn.commit()
conn.close()
def reencode_videos_av1():
# get videos
conn, cursor = config.get_local_db_connection()
cursor.execute("SELECT * FROM videos WHERE codec IS NULL AND status != 'missing' AND filepath IS NOT NULL ORDER BY size ASC;")
videos = cursor.fetchall()
for video in tqdm(videos, desc="Processing videos", unit="file"):
input_path = video['filepath']
if not os.path.exists(input_path):
print(f"🚫 File not found: {input_path}")
continue
file_size_in_mb = os.path.getsize(input_path) / (1024 * 1024)
print(f"\nProcessing {short_name} ({file_size_in_mb:.2f} MB)...")
print(f"\nProcessing {os.path.basename(input_path)} ({file_size_in_mb:.2f} MB)...")
# 2) Get current bitrate & resolution
current_bitrate, (width, height) = get_video_info(input_path)
@ -190,39 +167,21 @@ def reencode_videos_av1(input_folder):
if is_av1(input_path):
print("Video is already encoded in AV1. Skipping")
# move to 'encoded' folder inside the input folder
new_file_path = os.path.join(input_folder, "encoded", os.path.basename(input_path))
os.makedirs(os.path.dirname(new_file_path), exist_ok=True)
shutil.move(input_path, new_file_path)
update_codec_db(video['id'], 'av1')
continue
# 3) Re-encode
output_path = os.path.join('temp', os.path.basename(input_path))
encode_video(input_path, output_path, target_bitrate)
output_path = os.path.join('.temp', os.path.basename(input_path))
os.makedirs(os.path.dirname(output_path), exist_ok=True)
encoded = encode_video(input_path, output_path, target_bitrate)
if not encoded:
print("Encoding failed. Skipping.")
continue
# 4) Compare file sizes and replace if smaller
check_and_replace_if_smaller(input_path, output_path)
update_codec_db(video['id'], 'av1')
# move to 'encoded' folder inside the input folder
new_file_path = os.path.join(input_folder, "encoded", os.path.basename(input_path))
os.makedirs(os.path.dirname(new_file_path), exist_ok=True)
shutil.move(input_path, new_file_path)
# ---------------------- Main Script Entry ---------------------- #
if __name__ == "__main__":
import sys
if len(sys.argv) > 1:
input_folder = sys.argv[1]
else:
input_folder = input("Enter the input folder path: ")
if not os.path.isdir(input_folder):
print(f"Input folder '{input_folder}' does not exist.")
sys.exit(1)
print("Re-encoding videos to AV1 (only if bitrate is above our resolution-based presets)...")
reencode_videos_av1(input_folder)
print("All done!")
reencode_videos_av1()
Loading…
Cancel
Save