mirror of
https://github.com/meeb/tubesync.git
synced 2025-06-25 06:26:37 +00:00
Merge pull request #566 from tcely/patch-1
Some checks are pending
Some checks are pending
Sort video formats by height and bitrate
This commit is contained in:
commit
1981301ed6
@ -5,6 +5,7 @@
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
from .utils import multi_key_sort
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ def get_best_combined_format(media):
|
|||||||
'''
|
'''
|
||||||
for fmt in media.iter_formats():
|
for fmt in media.iter_formats():
|
||||||
# Check height matches
|
# Check height matches
|
||||||
if media.source.source_resolution.strip().upper() != fmt['format']:
|
if media.source.source_resolution_height != fmt['height']:
|
||||||
continue
|
continue
|
||||||
# Check the video codec matches
|
# Check the video codec matches
|
||||||
if media.source.source_vcodec != fmt['vcodec']:
|
if media.source.source_vcodec != fmt['vcodec']:
|
||||||
@ -47,7 +48,7 @@ def get_best_audio_format(media):
|
|||||||
Finds the best match for the source required audio format. If the source
|
Finds the best match for the source required audio format. If the source
|
||||||
has a 'fallback' of fail this can return no match.
|
has a 'fallback' of fail this can return no match.
|
||||||
'''
|
'''
|
||||||
# Order all audio-only formats by bitrate
|
# Reverse order all audio-only formats
|
||||||
audio_formats = []
|
audio_formats = []
|
||||||
for fmt in media.iter_formats():
|
for fmt in media.iter_formats():
|
||||||
# If the format has a video stream, skip it
|
# If the format has a video stream, skip it
|
||||||
@ -56,18 +57,18 @@ def get_best_audio_format(media):
|
|||||||
if not fmt['acodec']:
|
if not fmt['acodec']:
|
||||||
continue
|
continue
|
||||||
audio_formats.append(fmt)
|
audio_formats.append(fmt)
|
||||||
audio_formats = list(reversed(sorted(audio_formats, key=lambda k: k['abr'])))
|
|
||||||
if not audio_formats:
|
if not audio_formats:
|
||||||
# Media has no audio formats at all
|
# Media has no audio formats at all
|
||||||
return False, False
|
return False, False
|
||||||
# Find the highest bitrate audio format with a matching codec
|
audio_formats = list(reversed(audio_formats))
|
||||||
|
# Find the first audio format with a matching codec
|
||||||
for fmt in audio_formats:
|
for fmt in audio_formats:
|
||||||
if media.source.source_acodec == fmt['acodec']:
|
if media.source.source_acodec == fmt['acodec']:
|
||||||
# Matched!
|
# Matched!
|
||||||
return True, fmt['id']
|
return True, fmt['id']
|
||||||
# No codecs matched
|
# No codecs matched
|
||||||
if media.source.can_fallback:
|
if media.source.can_fallback:
|
||||||
# Can fallback, find the next highest bitrate non-matching codec
|
# Can fallback, find the next non-matching codec
|
||||||
return False, audio_formats[0]['id']
|
return False, audio_formats[0]['id']
|
||||||
else:
|
else:
|
||||||
# Can't fallback
|
# Can't fallback
|
||||||
@ -86,6 +87,7 @@ def get_best_video_format(media):
|
|||||||
return False, False
|
return False, False
|
||||||
# Filter video-only formats by resolution that matches the source
|
# Filter video-only formats by resolution that matches the source
|
||||||
video_formats = []
|
video_formats = []
|
||||||
|
sort_keys = [('height', False), ('vcodec', True), ('vbr', False)] # key, reverse
|
||||||
for fmt in media.iter_formats():
|
for fmt in media.iter_formats():
|
||||||
# If the format has an audio stream, skip it
|
# If the format has an audio stream, skip it
|
||||||
if fmt['acodec'] is not None:
|
if fmt['acodec'] is not None:
|
||||||
@ -94,6 +96,8 @@ def get_best_video_format(media):
|
|||||||
continue
|
continue
|
||||||
if media.source.source_resolution.strip().upper() == fmt['format']:
|
if media.source.source_resolution.strip().upper() == fmt['format']:
|
||||||
video_formats.append(fmt)
|
video_formats.append(fmt)
|
||||||
|
elif media.source.source_resolution_height == fmt['height']:
|
||||||
|
video_formats.append(fmt)
|
||||||
# Check we matched some streams
|
# Check we matched some streams
|
||||||
if not video_formats:
|
if not video_formats:
|
||||||
# No streams match the requested resolution, see if we can fallback
|
# No streams match the requested resolution, see if we can fallback
|
||||||
@ -109,13 +113,17 @@ def get_best_video_format(media):
|
|||||||
else:
|
else:
|
||||||
# Can't fallback
|
# Can't fallback
|
||||||
return False, False
|
return False, False
|
||||||
video_formats = list(reversed(sorted(video_formats, key=lambda k: k['height'])))
|
|
||||||
source_resolution = media.source.source_resolution.strip().upper()
|
|
||||||
source_vcodec = media.source.source_vcodec
|
|
||||||
if not video_formats:
|
if not video_formats:
|
||||||
# Still no matches
|
# Still no matches
|
||||||
return False, False
|
return False, False
|
||||||
|
video_formats = multi_key_sort(video_formats, sort_keys, True)
|
||||||
|
source_resolution = media.source.source_resolution.strip().upper()
|
||||||
|
source_vcodec = media.source.source_vcodec
|
||||||
exact_match, best_match = None, None
|
exact_match, best_match = None, None
|
||||||
|
for fmt in video_formats:
|
||||||
|
# format_note was blank, match height instead
|
||||||
|
if '' == fmt['format'] and fmt['height'] == media.source.source_resolution_height:
|
||||||
|
fmt['format'] = source_resolution
|
||||||
# Of our filtered video formats, check for resolution + codec + hdr + fps match
|
# Of our filtered video formats, check for resolution + codec + hdr + fps match
|
||||||
if media.source.prefer_60fps and media.source.prefer_hdr:
|
if media.source.prefer_60fps and media.source.prefer_hdr:
|
||||||
for fmt in video_formats:
|
for fmt in video_formats:
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import math
|
import math
|
||||||
|
from operator import itemgetter
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import requests
|
import requests
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
@ -134,6 +135,15 @@ def seconds_to_timestr(seconds):
|
|||||||
return '{:02d}:{:02d}:{:02d}'.format(hour, minutes, seconds)
|
return '{:02d}:{:02d}:{:02d}'.format(hour, minutes, seconds)
|
||||||
|
|
||||||
|
|
||||||
|
def multi_key_sort(sort_dict, specs, use_reversed=False):
|
||||||
|
result = list(sort_dict)
|
||||||
|
for key, reverse in reversed(specs):
|
||||||
|
result = sorted(result, key=itemgetter(key), reverse=reverse)
|
||||||
|
if use_reversed:
|
||||||
|
return list(reversed(result))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def normalize_codec(codec_str):
|
def normalize_codec(codec_str):
|
||||||
result = str(codec_str).upper()
|
result = str(codec_str).upper()
|
||||||
parts = result.split('.')
|
parts = result.split('.')
|
||||||
|
Loading…
Reference in New Issue
Block a user