mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-30 12:01:28 +00:00
[FfmpegMetadata] Allow setting metadata of individual streams
Closes #877
This commit is contained in:
parent
1797b073ed
commit
8896899216
|
@ -1547,7 +1547,7 @@ # MODIFYING METADATA
|
||||||
|
|
||||||
This option also has a few special uses:
|
This option also has a few special uses:
|
||||||
* You can download an additional URL based on the metadata of the currently downloaded video. To do this, set the field `additional_urls` to the URL that you want to download. Eg: `--parse-metadata "description:(?P<additional_urls>https?://www\.vimeo\.com/\d+)` will download the first vimeo video found in the description
|
* You can download an additional URL based on the metadata of the currently downloaded video. To do this, set the field `additional_urls` to the URL that you want to download. Eg: `--parse-metadata "description:(?P<additional_urls>https?://www\.vimeo\.com/\d+)` will download the first vimeo video found in the description
|
||||||
* You can use this to change the metadata that is embedded in the media file. To do this, set the value of the corresponding field with a `meta_` prefix. For example, any value you set to `meta_description` field will be added to the `description` field in the file. For example, you can use this to set a different "description" and "synopsis". Any value set to the `meta_` field will overwrite all default values.
|
* You can use this to change the metadata that is embedded in the media file. To do this, set the value of the corresponding field with a `meta_` prefix. For example, any value you set to `meta_description` field will be added to the `description` field in the file. For example, you can use this to set a different "description" and "synopsis". To modify the metadata of individual streams, use the `meta<n>_` prefix (Eg: `meta1_language`). Any value set to the `meta_` field will overwrite all default values.
|
||||||
|
|
||||||
For reference, these are the fields yt-dlp adds by default to the file metadata:
|
For reference, these are the fields yt-dlp adds by default to the file metadata:
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import collections
|
||||||
import io
|
import io
|
||||||
import itertools
|
import itertools
|
||||||
import os
|
import os
|
||||||
|
@ -728,15 +729,15 @@ def ffmpeg_escape(text):
|
||||||
yield ('-map_metadata', '1')
|
yield ('-map_metadata', '1')
|
||||||
|
|
||||||
def _get_metadata_opts(self, info):
|
def _get_metadata_opts(self, info):
|
||||||
metadata = {}
|
meta_prefix = 'meta'
|
||||||
meta_prefix = 'meta_'
|
metadata = collections.defaultdict(dict)
|
||||||
|
|
||||||
def add(meta_list, info_list=None):
|
def add(meta_list, info_list=None):
|
||||||
value = next((
|
value = next((
|
||||||
str(info[key]) for key in [meta_prefix] + list(variadic(info_list or meta_list))
|
str(info[key]) for key in [f'{meta_prefix}_'] + list(variadic(info_list or meta_list))
|
||||||
if info.get(key) is not None), None)
|
if info.get(key) is not None), None)
|
||||||
if value not in ('', None):
|
if value not in ('', None):
|
||||||
metadata.update({meta_f: value for meta_f in variadic(meta_list)})
|
metadata['common'].update({meta_f: value for meta_f in variadic(meta_list)})
|
||||||
|
|
||||||
# See [1-4] for some info on media metadata/metadata supported
|
# See [1-4] for some info on media metadata/metadata supported
|
||||||
# by ffmpeg.
|
# by ffmpeg.
|
||||||
|
@ -760,22 +761,26 @@ def add(meta_list, info_list=None):
|
||||||
add('episode_sort', 'episode_number')
|
add('episode_sort', 'episode_number')
|
||||||
if 'embed-metadata' in self.get_param('compat_opts', []):
|
if 'embed-metadata' in self.get_param('compat_opts', []):
|
||||||
add('comment', 'description')
|
add('comment', 'description')
|
||||||
metadata.pop('synopsis', None)
|
metadata['common'].pop('synopsis', None)
|
||||||
|
|
||||||
|
meta_regex = rf'{re.escape(meta_prefix)}(?P<i>\d+)?_(?P<key>.+)'
|
||||||
for key, value in info.items():
|
for key, value in info.items():
|
||||||
if value is not None and key != meta_prefix and key.startswith(meta_prefix):
|
mobj = re.fullmatch(meta_regex, key)
|
||||||
metadata[key[len(meta_prefix):]] = value
|
if value is not None and mobj:
|
||||||
|
metadata[mobj.group('i') or 'common'][mobj.group('key')] = value
|
||||||
|
|
||||||
for name, value in metadata.items():
|
for name, value in metadata['common'].items():
|
||||||
yield ('-metadata', f'{name}={value}')
|
yield ('-metadata', f'{name}={value}')
|
||||||
|
|
||||||
stream_idx = 0
|
stream_idx = 0
|
||||||
for fmt in info.get('requested_formats') or []:
|
for fmt in info.get('requested_formats') or []:
|
||||||
stream_count = 2 if 'none' not in (fmt.get('vcodec'), fmt.get('acodec')) else 1
|
stream_count = 2 if 'none' not in (fmt.get('vcodec'), fmt.get('acodec')) else 1
|
||||||
if fmt.get('language'):
|
lang = ISO639Utils.short2long(fmt['language']) or fmt.get('language')
|
||||||
lang = ISO639Utils.short2long(fmt['language']) or fmt['language']
|
for i in range(stream_idx, stream_idx + stream_count):
|
||||||
for i in range(stream_count):
|
if lang:
|
||||||
yield ('-metadata:s:%d' % (stream_idx + i), 'language=%s' % lang)
|
metadata[str(i)].setdefault('language', lang)
|
||||||
|
for name, value in metadata[str(i)].items():
|
||||||
|
yield (f'-metadata:s:{i}', f'{name}={value}')
|
||||||
stream_idx += stream_count
|
stream_idx += stream_count
|
||||||
|
|
||||||
def _get_infojson_opts(self, info, infofn):
|
def _get_infojson_opts(self, info, infofn):
|
||||||
|
|
Loading…
Reference in a new issue