fix: Fixed audio file suffix when quality is 'best' and minor UI fixes
This commit is contained in:
parent
8723ab0afe
commit
0311df0b06
5 changed files with 83 additions and 58 deletions
|
|
@ -211,9 +211,13 @@ class QualitySuffixValueTests(unittest.TestCase):
|
|||
def test_video_numeric_quality_gets_p_suffix(self):
|
||||
self.assertEqual(_quality_suffix_value(self._download_info(quality="2160")), "2160p")
|
||||
|
||||
def test_audio_best_stays_best(self):
|
||||
def test_audio_best_uses_actual_bitrate_template(self):
|
||||
info = self._download_info(download_type="audio", quality="best")
|
||||
self.assertEqual(_quality_suffix_value(info), "best")
|
||||
self.assertEqual(_quality_suffix_value(info), "%(abr).0fkbps")
|
||||
|
||||
def test_audio_numeric_quality_gets_kbps_suffix(self):
|
||||
info = self._download_info(download_type="audio", quality="192")
|
||||
self.assertEqual(_quality_suffix_value(info), "192kbps")
|
||||
|
||||
|
||||
class CodecSuffixValueTests(unittest.TestCase):
|
||||
|
|
@ -223,7 +227,7 @@ class CodecSuffixValueTests(unittest.TestCase):
|
|||
title="t",
|
||||
url="http://example.com/v",
|
||||
quality="best",
|
||||
download_type="video",
|
||||
download_type=kwargs.pop("download_type", "video"),
|
||||
codec=kwargs.pop("codec", "auto"),
|
||||
format="any",
|
||||
folder="",
|
||||
|
|
@ -250,6 +254,10 @@ class CodecSuffixValueTests(unittest.TestCase):
|
|||
info = self._download_info(entry={"vcodec": "some codec/name"})
|
||||
self.assertEqual(_codec_suffix_value(info), "some_codec_name")
|
||||
|
||||
def test_audio_has_no_codec_suffix(self):
|
||||
info = self._download_info(download_type="audio", codec="auto", entry={"acodec": "mp4a.40.2"})
|
||||
self.assertEqual(_codec_suffix_value(info), "")
|
||||
|
||||
|
||||
class DownloadInfoSetstateTests(unittest.TestCase):
|
||||
def _base_state(self, **kwargs):
|
||||
|
|
|
|||
11
app/ytdl.py
11
app/ytdl.py
|
|
@ -377,15 +377,24 @@ def _download_info_from_record(record: dict[str, Any]) -> DownloadInfo:
|
|||
|
||||
def _quality_suffix_value(dl: DownloadInfo) -> str:
|
||||
quality = str(getattr(dl, 'quality', '') or '')
|
||||
if getattr(dl, 'download_type', '') == 'video':
|
||||
download_type = getattr(dl, 'download_type', '')
|
||||
if download_type == 'video':
|
||||
if quality == 'best':
|
||||
return '%(height)sp'
|
||||
if re.fullmatch(r'\d+', quality):
|
||||
return f'{quality}p'
|
||||
if download_type == 'audio':
|
||||
if quality == 'best':
|
||||
return '%(abr).0fkbps'
|
||||
if re.fullmatch(r'\d+', quality):
|
||||
return f'{quality}kbps'
|
||||
return quality
|
||||
|
||||
|
||||
def _codec_suffix_value(dl: DownloadInfo) -> str:
|
||||
if getattr(dl, 'download_type', '') != 'video':
|
||||
return ''
|
||||
|
||||
codec_value = str(getattr(dl, 'codec', '') or '')
|
||||
if codec_value.lower() != 'auto':
|
||||
return codec_value
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
mytube:
|
||||
image: mytube
|
||||
image: tonyblu/mytube:latest
|
||||
container_name: mytube
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
|
|
@ -28,64 +26,66 @@ services:
|
|||
# - /path/to/robots.txt:/etc/robots.txt:ro
|
||||
|
||||
environment:
|
||||
ENV_FILE: ""
|
||||
|
||||
# === Container Setup ===
|
||||
# - PUID=1000
|
||||
# - PGID=1000
|
||||
# - UMASK=022
|
||||
# - DEFAULT_THEME=auto
|
||||
# - LOGLEVEL=INFO
|
||||
# - ENABLE_ACCESSLOG=false
|
||||
# PUID: "1000"
|
||||
# PGID: "1000"
|
||||
# UMASK: "022"
|
||||
# DEFAULT_THEME: auto
|
||||
# LOGLEVEL: INFO
|
||||
# ENABLE_ACCESSLOG: "false"
|
||||
|
||||
# === Directory Configuration ===
|
||||
# - DOWNLOAD_DIR=/downloads
|
||||
# - STATE_DIR=/downloads/.metube
|
||||
# - TEMP_DIR=/downloads
|
||||
# - AUDIO_DOWNLOAD_DIR=/audio
|
||||
# DOWNLOAD_DIR: /downloads
|
||||
# STATE_DIR: /downloads/.metube
|
||||
# TEMP_DIR: /downloads
|
||||
# AUDIO_DOWNLOAD_DIR: /audio
|
||||
|
||||
# === Web Server ===
|
||||
# - HOST=0.0.0.0
|
||||
# - PORT=8081
|
||||
- PUBLIC_MODE=true
|
||||
# - URL_PREFIX=/mytube/
|
||||
# - PUBLIC_HOST_URL=download/
|
||||
# - PUBLIC_HOST_AUDIO_URL=audio_download/
|
||||
# - HTTPS=false
|
||||
# - CERTFILE=/ssl/crt.pem
|
||||
# - KEYFILE=/ssl/key.pem
|
||||
# - CORS_ALLOWED_ORIGINS=
|
||||
# - ROBOTS_TXT=
|
||||
# HOST: 0.0.0.0
|
||||
# PORT: "8081"
|
||||
# PUBLIC_MODE: "false"
|
||||
# URL_PREFIX: /mytube/
|
||||
# PUBLIC_HOST_URL: download/
|
||||
# PUBLIC_HOST_AUDIO_URL: audio_download/
|
||||
# HTTPS: "false"
|
||||
# CERTFILE: /ssl/crt.pem
|
||||
# KEYFILE: /ssl/key.pem
|
||||
# CORS_ALLOWED_ORIGINS: ""
|
||||
# ROBOTS_TXT: ""
|
||||
|
||||
# === Download Behavior ===
|
||||
# - MAX_CONCURRENT_DOWNLOADS=3
|
||||
# - DELETE_FILE_ON_TRASHCAN=false
|
||||
# - DEFAULT_OPTION_PLAYLIST_ITEM_LIMIT=0
|
||||
# - SUBSCRIPTION_DEFAULT_CHECK_INTERVAL=60
|
||||
# - SUBSCRIPTION_SCAN_PLAYLIST_END=50
|
||||
# - SUBSCRIPTION_MAX_SEEN_IDS=50000
|
||||
# - CLEAR_COMPLETED_AFTER=0
|
||||
# MAX_CONCURRENT_DOWNLOADS: "3"
|
||||
# DELETE_FILE_ON_TRASHCAN: "false"
|
||||
# DEFAULT_OPTION_PLAYLIST_ITEM_LIMIT: "0"
|
||||
# SUBSCRIPTION_DEFAULT_CHECK_INTERVAL: "60"
|
||||
# SUBSCRIPTION_SCAN_PLAYLIST_END: "50"
|
||||
# SUBSCRIPTION_MAX_SEEN_IDS: "50000"
|
||||
# CLEAR_COMPLETED_AFTER: "0"
|
||||
|
||||
# === File Naming & Output ===
|
||||
# - OUTPUT_TEMPLATE=%(title)s.%(ext)s
|
||||
# - OUTPUT_TEMPLATE_CHAPTER=%(title)s - %(section_number)02d - %(section_title)s.%(ext)s
|
||||
# - OUTPUT_TEMPLATE_PLAYLIST=%(playlist_title)s/%(title)s.%(ext)s
|
||||
# - OUTPUT_TEMPLATE_CHANNEL=%(channel)s/%(title)s.%(ext)s
|
||||
# OUTPUT_TEMPLATE: "%(title)s.%(ext)s"
|
||||
# OUTPUT_TEMPLATE_CHAPTER: "%(title)s - %(section_number)02d - %(section_title)s.%(ext)s"
|
||||
# OUTPUT_TEMPLATE_PLAYLIST: "%(playlist_title)s/%(title)s.%(ext)s"
|
||||
# OUTPUT_TEMPLATE_CHANNEL: "%(channel)s/%(title)s.%(ext)s"
|
||||
|
||||
# === yt-dlp Options ===
|
||||
# - YTDL_OPTIONS={}
|
||||
# - YTDL_OPTIONS_FILE=/config/ytdl-options.json
|
||||
# - YTDL_OPTIONS_PRESETS={}
|
||||
# - YTDL_OPTIONS_PRESETS_FILE=/config/ytdl-presets.json
|
||||
# - ALLOW_YTDL_OPTIONS_OVERRIDES=false
|
||||
# YTDL_OPTIONS: "{}"
|
||||
# YTDL_OPTIONS_FILE: /config/ytdl-options.json
|
||||
# YTDL_OPTIONS_PRESETS: "{}"
|
||||
# YTDL_OPTIONS_PRESETS_FILE: /config/ytdl-presets.json
|
||||
# ALLOW_YTDL_OPTIONS_OVERRIDES: "false"
|
||||
|
||||
# === Directory Features ===
|
||||
# - CUSTOM_DIRS=true
|
||||
# - CREATE_CUSTOM_DIRS=true
|
||||
# - DOWNLOAD_DIRS_INDEXABLE=false
|
||||
# - CUSTOM_DIRS_EXCLUDE_REGEX=(^|/)[.@].*$
|
||||
# - CHOWN_DIRS=true
|
||||
# CUSTOM_DIRS: "true"
|
||||
# CREATE_CUSTOM_DIRS: "true"
|
||||
# DOWNLOAD_DIRS_INDEXABLE: "false"
|
||||
# CUSTOM_DIRS_EXCLUDE_REGEX: "(^|/)[.@].*$"
|
||||
# CHOWN_DIRS: "true"
|
||||
|
||||
# === Custom Environment File ===
|
||||
# - ENV_FILE=/path/to/custom.env
|
||||
# ENV_FILE: /path/to/custom.env
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://localhost:${PORT:-8081}/"]
|
||||
|
|
|
|||
|
|
@ -273,7 +273,8 @@
|
|||
[(ngModel)]="format"
|
||||
(change)="formatChanged()"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Subtitle output format for captions mode">
|
||||
ngbTooltip="Subtitle output format for captions mode"
|
||||
container="body">
|
||||
@for (f of formatOptions; track f.id) {
|
||||
<option [ngValue]="f.id">{{ f.text }}</option>
|
||||
}
|
||||
|
|
@ -291,13 +292,14 @@
|
|||
(change)="subtitleLanguageChanged()"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
placeholder="e.g. en, es, zh-Hans"
|
||||
ngbTooltip="Subtitle language (you can type any language code)">
|
||||
<datalist id="subtitleLanguageOptions">
|
||||
@for (lang of subtitleLanguages; track lang.id) {
|
||||
<option [value]="lang.id">{{ lang.text }}</option>
|
||||
}
|
||||
</datalist>
|
||||
ngbTooltip="Subtitle language (you can type any language code)"
|
||||
container="body">
|
||||
</div>
|
||||
<datalist id="subtitleLanguageOptions">
|
||||
@for (lang of subtitleLanguages; track lang.id) {
|
||||
<option [value]="lang.id">{{ lang.text }}</option>
|
||||
}
|
||||
</datalist>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 col-lg-3">
|
||||
<div class="input-group">
|
||||
|
|
@ -307,7 +309,8 @@
|
|||
[(ngModel)]="subtitleMode"
|
||||
(change)="subtitleModeChanged()"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Choose manual, auto, or fallback preference for captions mode">
|
||||
ngbTooltip="Choose manual, auto, or fallback preference for captions mode"
|
||||
container="body">
|
||||
@for (mode of subtitleModes; track mode.id) {
|
||||
<option [ngValue]="mode.id">{{ mode.text }}</option>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,11 @@ main
|
|||
border-color: color-mix(in srgb, var(--bs-primary) 55%, #fff)
|
||||
box-shadow: 0 0 0 .22rem color-mix(in srgb, var(--bs-primary) 20%, transparent)
|
||||
|
||||
.input-group:not(.has-validation) > .form-control:last-of-type:not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),
|
||||
.input-group:not(.has-validation) > .form-select:last-of-type:not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating)
|
||||
border-top-right-radius: var(--bs-border-radius)
|
||||
border-bottom-right-radius: var(--bs-border-radius)
|
||||
|
||||
.btn-primary
|
||||
box-shadow: 0 6px 16px color-mix(in srgb, var(--bs-primary) 28%, transparent)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue