Repository: yt-dlp/yt-dlp

Issue:
[TikTok] New API fix adds non-playable video codec in available formats
### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

- [X] I understand that I will be **blocked** if I *intentionally* remove or skip any mandatory\* field

### Checklist

- [X] I'm reporting that yt-dlp is broken on a **supported** site
- [X] I've verified that I have **updated yt-dlp to nightly or master** ([update instructions](https://github.com/yt-dlp/yt-dlp#update-channels))
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#video-url-contains-an-ampersand--and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [X] I've searched [known issues](https://github.com/yt-dlp/yt-dlp/issues/3766) and the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
- [X] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required

### Region

Global

### Provide a description that is worded well enough to be understood

Hi! New API fix adds for some videos a new codec bytevc2 which cannot be played by multimedia players (I used VLC). By default yt_dlp chooses normal codec, but I use `-S res:1080,vcodec:avc1,ext:mp4:m4a` format selection, so yt_dlp downloads video with this new codec.



### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [ ] If using API, add `'verbose': True` to `YoutubeDL` params instead
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
user@host:~$ python3 -m yt_dlp -F https://vm.tiktok.com/ZMMPDNEJL/
[vm.tiktok] Extracting URL: https://vm.tiktok.com/ZMMPDNEJL/
[vm.tiktok] ZMMPDNEJL: Downloading webpage
[TikTok] Extracting URL: https://www.tiktok.com/@soyko_max/video/7351538939712359713?_t=8l5sekUiLWo&_r=1
[TikTok] 7351538939712359713: Downloading video feed
[info] Available formats for 7351538939712359713:
ID                    EXT RESOLUTION │   FILESIZE  TBR PROTO │ VCODEC  ACODEC MORE INFO
───────────────────────────────────────────────────────────────────────────────────────────────────────────────
download_addr-0       mp4 720x1280   │    1.31MiB      https │ h264    aac    Download video, watermarked (API)
download_addr-1       mp4 720x1280   │    1.31MiB      https │ h264    aac    Download video, watermarked
download_addr-2       mp4 720x1280   │    1.31MiB      https │ h264    aac    Download video, watermarked
h264_540p_986746-0    mp4 1048x576   │    1.24MiB 986k https │ h264    aac    Direct video (API)
h264_540p_986746-1    mp4 1048x576   │    1.24MiB 986k https │ h264    aac    Direct video
h264_540p_986746-2    mp4 1048x576   │    1.24MiB 986k https │ h264    aac    Direct video
bytevc1_540p_263555-0 mp4 1048x576   │  339.96KiB 263k https │ h265    aac    Playback video (API)
bytevc1_540p_263555-1 mp4 1048x576   │  339.96KiB 263k https │ h265    aac    Playback video
bytevc1_540p_263555-2 mp4 1048x576   │  339.96KiB 263k https │ h265    aac    Playback video
bytevc1_540p_344910-0 mp4 1048x576   │  444.91KiB 344k https │ h265    aac    Playback video (API)
bytevc1_540p_344910-1 mp4 1048x576   │  444.91KiB 344k https │ h265    aac    Playback video
bytevc1_540p_344910-2 mp4 1048x576   │  444.91KiB 344k https │ h265    aac    Playback video
bytevc1_540p_507345-0 mp4 1048x576   │  654.43KiB 507k https │ h265    aac    Direct video (API)
bytevc1_540p_507345-1 mp4 1048x576   │  654.43KiB 507k https │ h265    aac    Direct video
bytevc1_540p_507345-2 mp4 1048x576   │  654.43KiB 507k https │ h265    aac    Direct video
bytevc2_720p_616180-0 mp4 1280x704   │  794.82KiB 616k https │ bytevc2 aac    Playback video (API)
bytevc2_720p_616180-1 mp4 1280x704   │  794.82KiB 616k https │ bytevc2 aac    Playback video
bytevc2_720p_616180-2 mp4 1280x704   │  794.82KiB 616k https │ bytevc2 aac    Playback video
bytevc1_720p_595186-0 mp4 1280x704   │  767.74KiB 595k https │ h265    aac    Playback video (API)
bytevc1_720p_595186-1 mp4 1280x704   │  767.74KiB 595k https │ h265    aac    Playback video
bytevc1_720p_595186-2 mp4 1280x704   │  767.74KiB 595k https │ h265    aac    Playback video

user@host:~$ python3 -m yt_dlp -vU -S res:1080,vcodec:avc1,ext:mp4:m4a https://vm.tiktok.com/ZMMPDNEJL/
[debug] Command-line config: ['-vU', '-S', 'res:1080,vcodec:avc1,ext:mp4:m4a', 'https://vm.tiktok.com/ZMMPDNEJL/']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2024.03.10 from yt-dlp/yt-dlp [615a84447]
[debug] Lazy loading extractors is disabled
[debug] Python 3.10.12 (CPython x86_64 64bit) - Linux-5.15.0-101-generic-x86_64-with-glibc2.35 (OpenSSL 3.0.2 15 Mar 2022, glibc 2.35)
[debug] exe versions: ffmpeg 4.4.2 (setts), ffprobe 4.4.2
[debug] Optional libraries: Cryptodome-3.20.0, brotli-1.1.0, certifi-2024.02.02, mutagen-1.47.0, requests-2.31.0, secretstorage-3.3.1, sqlite3-3.37.2, urllib3-2.2.1, websockets-12.0
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets
[debug] Loaded 1807 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: stable@2024.03.10 from yt-dlp/yt-dlp
yt-dlp is up to date (stable@2024.03.10 from yt-dlp/yt-dlp)
[vm.tiktok] Extracting URL: https://vm.tiktok.com/ZMMPDNEJL/
[vm.tiktok] ZMMPDNEJL: Downloading webpage
[TikTok] Extracting URL: https://www.tiktok.com/@soyko_max/video/7351538939712359713?_t=8l5sekUiLWo&_r=1
[debug] [TikTok] iid=7351149742343391009
[TikTok] 7351538939712359713: Downloading video feed
[debug] Sort order given by user: res:1080, vcodec:avc1, ext:mp4:m4a
[debug] Sort order given by extractor: quality, codec, size, br
[debug] Formats sorted by: hasvid, ie_pref, res:1080(1080.0), vcodec:avc1(7), vext:mp4(6), aext:m4a(8), quality, acodec, size, br, lang, fps, hdr:12(7), channels, asr, proto, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 7351538939712359713: Downloading 1 format(s): bytevc2_720p_616180-2
[debug] Invoking http downloader on "https://v16m.byteicdn.com/366e989edb75b43b4e545b0f6f94180e/6607a32c/video/tos/useast2a/tos-useast2a-ve-0068-euttp/oIEDMCMe2rmeIExnh6mGk70AEkerG1aIRgfFj6/?a=0&bti=OHYpOTY0Zik3OjlmOm01MzE6ZDQ0MDo%3D&ch=0&cr=13&dr=0&lr=all&cd=0%7C0%7C0%7C&cv=1&br=1202&bt=601&cs=5&ds=3&ft=teSL~8QLodzR12NvvEh3hIxR34DaRq_45SY&mime_type=video_mp4&qs=14&rc=aTwzOGdkOGRnMzw1NDQ1OUBpam9pbng5cjx4cjMzZjczM0AvL18yYmBgXjMxXy4tLy5eYSNsa2FnMmRrZy9gLS1kMWNzcw%3D%3D&vvpl=1&l=20240329232904ECF8D33243F1CE142F0B&btag=e00088000&cc=10"
[download] Destination: Оригинал) [7351538939712359713].mp4
[download] 100% of  794.82KiB in 00:00:00 at 7.49MiB/s
```



Discussion:
https://inf.news/en/tech/4f0ac5f574a31acd3a7cdfb51da3e25e.html

> ByteDance Advanced Video Group independently developed BVC2. 0 The encoder stands out from the competition: it won the first place in the VMAF, PSNR avg. MSE two criterion tests. At the same time, it also ranked first in the PSNR avg. log and SSIM two criterion tests.

It's a proprietary codec that was possibly specifically developed to be unplayable outside of bytedance's apps.

Workaround: `--extractor-args "tiktok:app_version=27.8.1;manifest_app_version=2022708010"`

I'll have a PR up later tonight


Resolving patch:
diff --git a/yt_dlp/extractor/tiktok.py b/yt_dlp/extractor/tiktok.py
--- a/yt_dlp/extractor/tiktok.py
+++ b/yt_dlp/extractor/tiktok.py
@@ -274,6 +274,7 @@ def audio_meta(url):
 
         def extract_addr(addr, add_meta={}):
             parsed_meta, res = parse_url_key(addr.get('url_key', ''))
+            is_bytevc2 = parsed_meta.get('vcodec') == 'bytevc2'
             if res:
                 known_resolutions.setdefault(res, {}).setdefault('height', int_or_none(addr.get('height')))
                 known_resolutions[res].setdefault('width', int_or_none(addr.get('width')))
@@ -286,8 +287,11 @@ def extract_addr(addr, add_meta={}):
                 'acodec': 'aac',
                 'source_preference': -2 if 'aweme/v1' in url else -1,  # Downloads from API might get blocked
                 **add_meta, **parsed_meta,
+                # bytevc2 is bytedance's proprietary (unplayable) video codec
+                'preference': -100 if is_bytevc2 else -1,
                 'format_note': join_nonempty(
-                    add_meta.get('format_note'), '(API)' if 'aweme/v1' in url else None, delim=' '),
+                    add_meta.get('format_note'), '(API)' if 'aweme/v1' in url else None,
+                    '(UNPLAYABLE)' if is_bytevc2 else None, delim=' '),
                 **audio_meta(url),
             } for url in addr.get('url_list') or []]
 


Test patch: