diff --git a/CHANGELOG.md b/CHANGELOG.md
index d8f0991b..868704b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,12 @@
+
+
+# Changes
+- Add more fine-grained options for video container/codec selection.
+
+## Fixes
+
+## Features
+
# Changes
diff --git a/poetry.lock b/poetry.lock
index ed753f74..b942257e 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -75,33 +75,33 @@ lxml = ["lxml"]
[[package]]
name = "black"
-version = "24.10.0"
+version = "25.1.0"
description = "The uncompromising code formatter."
optional = false
python-versions = ">=3.9"
files = [
- {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"},
- {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"},
- {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"},
- {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"},
- {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"},
- {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"},
- {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"},
- {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"},
- {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"},
- {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"},
- {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"},
- {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"},
- {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"},
- {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"},
- {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"},
- {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"},
- {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"},
- {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"},
- {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"},
- {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"},
- {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"},
- {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"},
+ {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"},
+ {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"},
+ {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"},
+ {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"},
+ {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"},
+ {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"},
+ {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"},
+ {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"},
+ {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"},
+ {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"},
+ {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"},
+ {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"},
+ {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"},
+ {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"},
+ {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"},
+ {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"},
+ {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"},
+ {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"},
+ {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"},
+ {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"},
+ {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"},
+ {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"},
]
[package.dependencies]
@@ -261,13 +261,13 @@ files = [
[[package]]
name = "certifi"
-version = "2024.12.14"
+version = "2025.1.31"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.6"
files = [
- {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"},
- {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"},
+ {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"},
+ {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"},
]
[[package]]
@@ -764,17 +764,18 @@ files = [
[[package]]
name = "isort"
-version = "5.13.2"
+version = "6.0.0"
description = "A Python utility / library to sort Python imports."
optional = false
-python-versions = ">=3.8.0"
+python-versions = ">=3.9.0"
files = [
- {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"},
- {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"},
+ {file = "isort-6.0.0-py3-none-any.whl", hash = "sha256:567954102bb47bb12e0fae62606570faacddd441e45683968c8d1734fb1af892"},
+ {file = "isort-6.0.0.tar.gz", hash = "sha256:75d9d8a1438a9432a7d7b54f2d3b45cad9a4a0fdba43617d9873379704a8bdf1"},
]
[package.extras]
-colors = ["colorama (>=0.4.6)"]
+colors = ["colorama"]
+plugins = ["setuptools"]
[[package]]
name = "jaraco-classes"
@@ -1501,13 +1502,13 @@ hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"]
[[package]]
name = "pyinstaller-hooks-contrib"
-version = "2025.0"
+version = "2025.1"
description = "Community maintained hooks for PyInstaller"
optional = false
python-versions = ">=3.8"
files = [
- {file = "pyinstaller_hooks_contrib-2025.0-py3-none-any.whl", hash = "sha256:3c0623799c3f81a37293127f485d65894c20fd718f722cb588785a3e52581ad1"},
- {file = "pyinstaller_hooks_contrib-2025.0.tar.gz", hash = "sha256:6dc0b55a1acaab2ffee36ed4a05b073aa0a22e46f25fb5c66a31e217454135ed"},
+ {file = "pyinstaller_hooks_contrib-2025.1-py3-none-any.whl", hash = "sha256:d3c799470cbc0bda60dcc8e6b4ab976777532b77621337f2037f558905e3a8e9"},
+ {file = "pyinstaller_hooks_contrib-2025.1.tar.gz", hash = "sha256:130818f9e9a0a7f2261f1fd66054966a3a50c99d000981c5d1db11d3ad0c6ab2"},
]
[package.dependencies]
@@ -1516,20 +1517,20 @@ setuptools = ">=42.0.0"
[[package]]
name = "pylint"
-version = "3.3.3"
+version = "3.3.4"
description = "python code static checker"
optional = false
python-versions = ">=3.9.0"
files = [
- {file = "pylint-3.3.3-py3-none-any.whl", hash = "sha256:26e271a2bc8bce0fc23833805a9076dd9b4d5194e2a02164942cb3cdc37b4183"},
- {file = "pylint-3.3.3.tar.gz", hash = "sha256:07c607523b17e6d16e2ae0d7ef59602e332caa762af64203c24b41c27139f36a"},
+ {file = "pylint-3.3.4-py3-none-any.whl", hash = "sha256:289e6a1eb27b453b08436478391a48cd53bb0efb824873f949e709350f3de018"},
+ {file = "pylint-3.3.4.tar.gz", hash = "sha256:74ae7a38b177e69a9b525d0794bd8183820bfa7eb68cc1bee6e8ed22a42be4ce"},
]
[package.dependencies]
astroid = ">=3.3.8,<=3.4.0-dev0"
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
dill = {version = ">=0.3.7", markers = "python_version >= \"3.12\""}
-isort = ">=4.2.5,<5.13.0 || >5.13.0,<6"
+isort = ">=4.2.5,<5.13.0 || >5.13.0,<7"
mccabe = ">=0.6,<0.8"
platformdirs = ">=2.2.0"
tomlkit = ">=0.10.1"
diff --git a/src/usdb_syncer/gui/forms/SettingsDialog.ui b/src/usdb_syncer/gui/forms/SettingsDialog.ui
index 0af519e6..401e8eda 100644
--- a/src/usdb_syncer/gui/forms/SettingsDialog.ui
+++ b/src/usdb_syncer/gui/forms/SettingsDialog.ui
@@ -489,7 +489,7 @@
-
- Container:
+ Container/codec:
@@ -501,6 +501,9 @@
0
+
+ <html><head/><body><p>For <span style=" font-weight:700;">UltraStar deluxe</span>, <span style=" font-weight:700;">Performous</span>, <span style=" font-weight:700;">Vocaluxe</span> or other ffmpeg-based karaoke softwares, choose "Best available container/codec" or "mp4 (best available codec)" if you prefer to have an mp4 container.</p><p>For <span style=" font-weight:700;">UltraStar CMD</span> (Windows), <span style=" font-weight:700;">Melody Mania</span> (Windows) and low-power computers, choose "mp4 (AVC/H.264).</p><p>Otherwise, select a container/codec option that your software supports.</p><p>If the selected container/format option is not available for a given song, the syncer will try to at least get the requested container, and if that is not available either, it will fallback to the best available container/codec.</p></body></html>
+
-
diff --git a/src/usdb_syncer/settings.py b/src/usdb_syncer/settings.py
index 0ed69b88..c0e4957c 100644
--- a/src/usdb_syncer/settings.py
+++ b/src/usdb_syncer/settings.py
@@ -381,32 +381,42 @@ def cookies(self) -> CookieJar | None:
class VideoContainer(Enum):
"""Video containers that can be requested when downloading with ytdl."""
+ BEST = "bestvideo"
MP4 = "mp4"
- MP4_NO_VP9 = "mp4_no_vp9"
+ MP4_AV1 = "mp4_av1"
+ MP4_AVC = "mp4_avc"
+ MP4_VP9 = "mp4_vp9"
WEBM = "webm"
- BEST = "bestvideo"
def __str__(self) -> str:
match self:
+ case VideoContainer.BEST:
+ return "Best available container/codec"
case VideoContainer.MP4:
- return ".mp4 (any codec)"
- case VideoContainer.MP4_NO_VP9:
- return ".mp4 (no VP9)"
+ return ".mp4 (best available codec)"
+ case VideoContainer.MP4_AV1:
+ return ".mp4 (AV1 codec)"
+ case VideoContainer.MP4_AVC:
+ return ".mp4 (AVC/H.264 codec)"
+ case VideoContainer.MP4_VP9:
+ return ".mp4 (VP9 codec)"
case VideoContainer.WEBM:
- return ".webm (VP9)"
- case VideoContainer.BEST:
- return "Best available"
+ return ".webm (VP9 codec)"
case _ as unreachable:
assert_never(unreachable)
def ytdl_format(self) -> str:
match self:
- case VideoContainer.MP4 | VideoContainer.WEBM:
- return f"bestvideo*[ext={self.value}]"
- case VideoContainer.MP4_NO_VP9:
- return "bestvideo*[ext=mp4][vcodec!~='vp0?9']"
case VideoContainer.BEST:
return "bestvideo*"
+ case VideoContainer.MP4 | VideoContainer.WEBM:
+ return f"bestvideo*[ext={self.value}]/bestvideo*"
+ case VideoContainer.MP4_AV1:
+ return "bestvideo*[ext=mp4][vcodec~='^av01']/bestvideo*[ext=mp4]/bestvideo*"
+ case VideoContainer.MP4_AVC:
+ return "bestvideo*[ext=mp4][vcodec~='^(avc|h264)']/bestvideo*[ext=mp4]/bestvideo*"
+ case VideoContainer.MP4_VP9:
+ return "bestvideo*[ext=mp4][vcodec~='^vp0?9']/bestvideo*[ext=mp4]/bestvideo*"
case _ as unreachable:
assert_never(unreachable)
diff --git a/src/usdb_syncer/song_txt/headers.py b/src/usdb_syncer/song_txt/headers.py
index 3fa4c644..304c8c27 100644
--- a/src/usdb_syncer/song_txt/headers.py
+++ b/src/usdb_syncer/song_txt/headers.py
@@ -185,6 +185,7 @@ def _set_header_value(kwargs: dict[str, Any], header: str, value: str) -> None:
header = "creator" if header == "AUTHOR" else header.lower()
if header in (
"artist",
+ "version",
"language",
"edition",
"genre",
@@ -193,12 +194,16 @@ def _set_header_value(kwargs: dict[str, Any], header: str, value: str) -> None:
"creator",
"mp3",
"audio",
+ "audiourl",
"vocals",
"instrumental",
"cover",
+ "coverurl",
"background",
- "relative",
+ "backgroundurl",
"video",
+ "videourl",
+ "relative",
"p1",
"p2",
"encoding",