Repository: yt-dlp/yt-dlp

Issue:
Downloading DASH streams from rozhlas.cz
### 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 asking a question and **not** reporting a bug or requesting a feature
- [X] I've looked through the [README](https://github.com/yt-dlp/yt-dlp#readme)
- [X] I've verified that I'm running yt-dlp version **2023.03.04** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
- [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 questions **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)

### Please make sure the question is worded well enough to be understood

I'm trying to download audio from the website of czech radio - rozhlas.cz (dvojka.rozhlas.cz in this case - one of the stations).
Some audios are served as MP3, those are downloaded alright as an MP3 file. ([example](https://dvojka.rozhlas.cz/pres-30-let-ovlivnovala-nas-kulturni-zivot-jako-muz-osudove-zeny-ludmila-7458776))

But [this one](https://dvojka.rozhlas.cz/karel-siktanc-cerny-jezdec-bily-kun-napinava-pohadka-o-tajemnem-prizraku-8946969) is streamed and when I run the download, I get the .dash file only.

If I view the page in the browser and find the URL of the .mpd file, I can then run yt-dlp.exe https://croaod.cz/stream/8f083d82-539d-4aa2-9e37-57a7537ef6c6.m4a/manifest.mpd and it downloads as a manifest [manifest].m4a.

Are there some command line parameters that I can use to have the file downloaded as an mp3?

Let me know if you need more information. This is my first posting here so I apologize in advance if I didn't do something right.

Thank you.

### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [X] 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
[debug] Command-line config: ['-vU', 'https://dvojka.rozhlas.cz/karel-siktanc-cerny-jezdec-bily-kun-napinava-pohadka-o-tajemnem-prizraku-8946969']
[debug] Encodings: locale cp1250, fs utf-8, pref cp1250, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.03.04 [392389b7d] (win_exe)
[debug] Python 3.8.10 (CPython AMD64 64bit) - Windows-10-10.0.19044-SP0 (OpenSSL 1.1.1k  25 Mar 2021)
[debug] exe versions: ffmpeg 6.0-essentials_build-www.gyan.dev (setts)
[debug] Optional libraries: Cryptodome-3.17, brotli-1.0.9, certifi-2022.12.07, mutagen-1.46.0, sqlite3-2.6.0, websockets-10.4
[debug] Proxy map: {}
[debug] Loaded 1786 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Available version: stable@2023.03.04, Current version: stable@2023.03.04
Current Build Hash: 5590c57bd0433ed239a2deaaf92e2ad6f37fe50f53664c821575cafe106a9421
yt-dlp is up to date (stable@2023.03.04)
[RozhlasVltava] Extracting URL: https://dvojka.rozhlas.cz/karel-siktanc-cerny-jezdec-bily-kun-napinava-pohadka-o-tajemnem-prizraku-8946969
[RozhlasVltava] 8946969: Downloading webpage
[download] Downloading playlist: Karel Šiktanc: Černý jezdec, bílý kůň. Napínavá pohádka o tajemném přízraku
[RozhlasVltava] Playlist Karel Šiktanc: Černý jezdec, bílý kůň. Napínavá pohádka o tajemném přízraku: Downloading 1 items of 1
[download] Downloading item 1 of 1
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 10631121: Downloading 1 format(s): dash
[debug] Invoking http downloader on "https://croaod.cz/stream/8f083d82-539d-4aa2-9e37-57a7537ef6c6.m4a/manifest.mpd"
[debug] File locking is not supported. Proceeding without locking
[download] Destination: Karel Šiktanc： Černý jezdec, bílý kůň. Napínavá pohádka o tajemném přízraku [10631121].dash
[download] 100% of    8.02KiB in 00:00:00 at 113.93KiB/s
[download] Finished downloading playlist: Karel Šiktanc: Černý jezdec, bílý kůň. Napínavá pohádka o tajemném přízraku
```



Discussion:

Resolving patch:
diff --git a/yt_dlp/extractor/rozhlas.py b/yt_dlp/extractor/rozhlas.py
--- a/yt_dlp/extractor/rozhlas.py
+++ b/yt_dlp/extractor/rozhlas.py
@@ -1,5 +1,12 @@
 from .common import InfoExtractor
-from ..utils import extract_attributes, int_or_none, remove_start, traverse_obj
+from ..utils import (
+    extract_attributes,
+    int_or_none,
+    remove_start,
+    str_or_none,
+    traverse_obj,
+    url_or_none,
+)
 
 
 class RozhlasIE(InfoExtractor):
@@ -50,7 +57,7 @@ class RozhlasVltavaIE(InfoExtractor):
         'url': 'https://wave.rozhlas.cz/papej-masicko-porcujeme-a-bilancujeme-filmy-a-serialy-ktere-letos-zabily-8891337',
         'md5': 'ba2fdbc1242fc16771c7695d271ec355',
         'info_dict': {
-            'id': 8891337,
+            'id': '8891337',
             'title': 'md5:21f99739d04ab49d8c189ec711eef4ec',
         },
         'playlist_count': 1,
@@ -69,7 +76,7 @@ class RozhlasVltavaIE(InfoExtractor):
     }, {
         'url': 'https://wave.rozhlas.cz/poslechnete-si-neklid-podcastovy-thriller-o-vine-strachu-a-vztahu-ktery-zasel-8554744',
         'info_dict': {
-            'id': 8554744,
+            'id': '8554744',
             'title': 'Poslechněte si Neklid. Podcastový thriller o vině, strachu a vztahu, který zašel příliš daleko',
         },
         'playlist_count': 5,
@@ -139,27 +146,62 @@ class RozhlasVltavaIE(InfoExtractor):
                 'chapter_number': 5,
             },
         }]
+    }, {
+        'url': 'https://dvojka.rozhlas.cz/karel-siktanc-cerny-jezdec-bily-kun-napinava-pohadka-o-tajemnem-prizraku-8946969',
+        'info_dict': {
+            'id': '8946969',
+            'title': 'Karel Šiktanc: Černý jezdec, bílý kůň. Napínavá pohádka o tajemném přízraku',
+        },
+        'playlist_count': 1,
+        'playlist': [{
+            'info_dict': {
+                'id': '10631121',
+                'ext': 'm4a',
+                'title': 'Karel Šiktanc: Černý jezdec, bílý kůň. Napínavá pohádka o tajemném přízraku',
+                'description': 'Karel Šiktanc: Černý jezdec, bílý kůň',
+                'duration': 2656,
+                'artist': 'Tvůrčí skupina Drama a literatura',
+                'channel_id': 'dvojka',
+            },
+        }],
+        'params': {'skip_download': 'dash'},
     }]
 
     def _extract_video(self, entry):
-        chapter_number = int_or_none(traverse_obj(entry, ('meta', 'ga', 'contentSerialPart')))
+        formats = []
+        audio_id = entry['meta']['ga']['contentId']
+        for audio in traverse_obj(entry, ('audioLinks', lambda _, v: url_or_none(v['url']))):
+            ext = audio.get('variant')
+            if ext == 'dash':
+                formats.extend(self._extract_mpd_formats(
+                    audio['url'], audio_id, mpd_id=ext, fatal=False))
+            elif ext == 'hls':
+                formats.extend(self._extract_m3u8_formats(
+                    audio['url'], audio_id, 'm4a', m3u8_id=ext, fatal=False))
+            else:
+                formats.append({
+                    'url': audio['url'],
+                    'ext': ext,
+                    'format_id': ext,
+                    'abr': int_or_none(audio.get('bitrate')),
+                    'acodec': ext,
+                    'vcodec': 'none',
+                })
+
+        chapter_number = traverse_obj(entry, ('meta', 'ga', 'contentSerialPart', {int_or_none}))
+
         return {
-            'id': entry['meta']['ga']['contentId'],
-            'title': traverse_obj(entry, ('meta', 'ga', 'contentName')),
-            'description': entry.get('title'),
-            'duration': entry.get('duration'),
-            'artist': traverse_obj(entry, ('meta', 'ga', 'contentAuthor')),
-            'channel_id': traverse_obj(entry, ('meta', 'ga', 'contentCreator')),
+            'id': audio_id,
             'chapter': traverse_obj(entry, ('meta', 'ga', 'contentNameShort')) if chapter_number else None,
             'chapter_number': chapter_number,
-            'formats': [{
-                'url': audio_link['url'],
-                'ext': audio_link.get('variant'),
-                'format_id': audio_link.get('variant'),
-                'abr': audio_link.get('bitrate'),
-                'acodec': audio_link.get('variant'),
-                'vcodec': 'none',
-            } for audio_link in entry['audioLinks']],
+            'formats': formats,
+            **traverse_obj(entry, {
+                'title': ('meta', 'ga', 'contentName'),
+                'description': 'title',
+                'duration': ('duration', {int_or_none}),
+                'artist': ('meta', 'ga', 'contentAuthor'),
+                'channel_id': ('meta', 'ga', 'contentCreator'),
+            })
         }
 
     def _real_extract(self, url):
@@ -173,7 +215,7 @@ def _real_extract(self, url):
 
         return {
             '_type': 'playlist',
-            'id': data.get('embedId'),
+            'id': str_or_none(data.get('embedId')) or video_id,
             'title': traverse_obj(data, ('series', 'title')),
             'entries': map(self._extract_video, data['playlist']),
         }


Test patch: