Skip to content

Instantly share code, notes, and snippets.

@Saren-Arterius
Last active September 30, 2024 20:15
Show Gist options
  • Save Saren-Arterius/a1f6d7563a20467981e2fe212955b9de to your computer and use it in GitHub Desktop.
Save Saren-Arterius/a1f6d7563a20467981e2fe212955b9de to your computer and use it in GitHub Desktop.
/usr/lib/jellyfin-ffmpeg/ffmpeg
  • Just move /usr/lib/jellyfin-ffmpeg/ffmpeg to /usr/lib/jellyfin-ffmpeg/ffmpeg.orig, and create /usr/lib/jellyfin-ffmpeg/ffmpeg with the code, and don't forget sudo chmod +x /usr/lib/jellyfin-ffmpeg/ffmpeg

  • if your cpu is not as strong as 13900h, or you want to support multiple users, you can lower height_preset_*.

  • require mediainfo

#!/usr/bin/env python3
import sys
import subprocess
import re
import json
import math
height_preset_480 = 5
height_preset_720 = 5
height_preset_1080 = 7
def get_original_resolution(file_path):
try:
result = subprocess.run(['mediainfo', '--Output=JSON', file_path],
capture_output=True, text=True, check=True)
info = json.loads(result.stdout)
video_track = next(track for track in info['media']['track'] if track['@type'] == 'Video')
return int(video_track['Width']), int(video_track['Height'])
except Exception as e:
print(f"Error getting video information: {e}", file=sys.stderr)
return None, None
def modify_arguments(args):
new_args = []
scale_vaapi_index = None
scale_index = None
new_width = None
new_height = None
new_preset = None
input_file = None
# First pass to find input file, scale_vaapi, and filter_complex
for i, arg in enumerate(args):
if arg == '-i':
input_file = args[i+1].split(':', 1)[-1] # Remove 'file:' prefix if present
elif 'scale_vaapi=' in arg:
scale_vaapi_index = i
elif 'scale=' in arg:
scale_index = i
if not input_file:
print("Error: Input file not found in arguments", file=sys.stderr)
return args
original_width, original_height = get_original_resolution(input_file)
if not original_height:
return args # Return original args if we couldn't get the video info
# Determine new height and preset
match = None
if scale_vaapi_index is not None:
match = re.search(r'scale_vaapi=w=(\d+):h=(\d+)', args[scale_vaapi_index])
if scale_index is not None:
match = re.search(r'scale=(.+):(.+),', args[scale_index])
if match:
try:
requested_width = int(match.group(1))
requested_height = int(match.group(2))
except Exception as e:
requested_width = 480
requested_height = 272
if requested_height <= 480 and original_height >= 720:
new_height = 720
new_preset = height_preset_720
elif requested_height <= 240 and original_height >= 480:
new_height = 480
new_preset = height_preset_480
else:
new_height = min(requested_height, original_height)
if new_height <= 480:
new_preset = height_preset_480
elif new_height <= 720:
new_preset = height_preset_720
elif new_height <= 1080:
new_preset = height_preset_1080
if new_height:
new_width = math.ceil(original_width * (new_height / original_height) / 4) * 4
else:
if original_height <= 480:
new_preset = height_preset_480
elif original_height <= 720:
new_preset = height_preset_720
elif original_height <= 1080:
new_preset = height_preset_1080
# Second pass to modify arguments
skip = False
for i, arg in enumerate(args):
if skip:
skip = False
continue
if i == scale_index and new_width and new_height:
scale = arg
scale = re.sub(r'scale=(.+):(.+),', f'scale=-2:{new_height},', scale)
new_args.append(scale)
elif i == scale_vaapi_index and new_width and new_height:
filter_complex = arg
filter_complex = re.sub(r'scale=-1:(\d+):', f'scale=-1:{new_height}:', filter_complex)
filter_complex = re.sub(r'pad=max\((\d+)\\,', f'pad=max({new_width}\\,', filter_complex)
# Update pad height
filter_complex = re.sub(r':max\((\d+)\\,', f':max({new_height}\\,', filter_complex)
# Update crop dimensions
filter_complex = re.sub(r'crop=(\d+):(\d+)', f'crop={new_width}:{new_height}', filter_complex)
# Update scale_vaapi dimensions
filter_complex = re.sub(r'scale_vaapi=w=(\d+):h=(\d+)', f'scale_vaapi=w={new_width}:h={new_height}', filter_complex)
new_args.append(filter_complex)
elif arg == '-preset':
if new_preset:
new_args.append(arg)
new_args.append(str(new_preset))
else:
new_args.append(arg)
new_args.append(args[i+1])
skip = True # Skip the next argument as we've handled it
else:
new_args.append(arg)
return new_args
def main():
# The path to the real ffmpeg executable
real_ffmpeg = "/usr/lib/jellyfin-ffmpeg/ffmpeg.orig"
# Get all command line arguments except the script name
args = sys.argv[1:]
# Modify the arguments
modified_args = modify_arguments(args)
# Construct the new command
command = [real_ffmpeg] + modified_args
# Execute the modified ffmpeg command
try:
result = subprocess.run(command, check=True)
except subprocess.CalledProcessError as e:
print(f"Error executing ffmpeg: {e}", file=sys.stderr)
sys.exit(e.returncode)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment