introduce new '--add-music-metadata' options

This commit is contained in:
Ali Fardan 2020-02-05 09:08:11 +03:00
parent 705b1cda99
commit f9c127b989
4 changed files with 63 additions and 0 deletions

View File

@ -276,6 +276,8 @@ def _real_main(argv=None):
# so metadata can be added here. # so metadata can be added here.
if opts.addmetadata: if opts.addmetadata:
postprocessors.append({'key': 'FFmpegMetadata'}) postprocessors.append({'key': 'FFmpegMetadata'})
if opts.addmusicmetadata:
postprocessors.append({'key': 'FFmpegMusicMetadata'})
if opts.convertsubtitles: if opts.convertsubtitles:
postprocessors.append({ postprocessors.append({
'key': 'FFmpegSubtitlesConvertor', 'key': 'FFmpegSubtitlesConvertor',

View File

@ -818,6 +818,10 @@ def parseOpts(overrideArguments=None):
'--add-metadata', '--add-metadata',
action='store_true', dest='addmetadata', default=False, action='store_true', dest='addmetadata', default=False,
help='Write metadata to the video file') help='Write metadata to the video file')
postproc.add_option(
'--add-music-metadata',
action='store_true', dest='addmusicmetadata', default=False,
help='Write music metadata to video file (this works only for songs from music.youtube.com)')
postproc.add_option( postproc.add_option(
'--metadata-from-title', '--metadata-from-title',
metavar='FORMAT', dest='metafromtitle', metavar='FORMAT', dest='metafromtitle',

View File

@ -10,6 +10,7 @@ from .ffmpeg import (
FFmpegFixupM4aPP, FFmpegFixupM4aPP,
FFmpegMergerPP, FFmpegMergerPP,
FFmpegMetadataPP, FFmpegMetadataPP,
FFmpegMusicMetadataPP,
FFmpegVideoConvertorPP, FFmpegVideoConvertorPP,
FFmpegSubtitlesConvertorPP, FFmpegSubtitlesConvertorPP,
) )
@ -32,6 +33,7 @@ __all__ = [
'FFmpegFixupStretchedPP', 'FFmpegFixupStretchedPP',
'FFmpegMergerPP', 'FFmpegMergerPP',
'FFmpegMetadataPP', 'FFmpegMetadataPP',
'FFmpegMusicMetadataPP',
'FFmpegPostProcessor', 'FFmpegPostProcessor',
'FFmpegSubtitlesConvertorPP', 'FFmpegSubtitlesConvertorPP',
'FFmpegVideoConvertorPP', 'FFmpegVideoConvertorPP',

View File

@ -502,6 +502,61 @@ class FFmpegMetadataPP(FFmpegPostProcessor):
os.rename(encodeFilename(temp_filename), encodeFilename(filename)) os.rename(encodeFilename(temp_filename), encodeFilename(filename))
return [], info return [], info
class FFmpegMusicMetadataPP(FFmpegPostProcessor):
def run(self, info):
metadata = {}
# Any original music (even singles) provided from music.youtube.com will
# contain 'album' JSON field, if not, its just like any other video
if info.get('album') is None:
self._downloader.to_screen('[ffmpeg] No music metadata found, nothing to add')
return [], info
metadata['title'] = info['track']
metadata['date'] = info['release_year']
metadata['artist'] = info['artist']
metadata['album'] = info['album']
if info.get('playlist_index') is not None:
metadata['track'] = '%d/%d' % (info['playlist_index'], info['n_entries'])
filename = info['filepath']
temp_filename = prepend_extension(filename, 'temp')
in_filenames = [filename]
options = []
if info['ext'] == 'm4a':
options.extend(['-vn', '-acodec', 'copy'])
else:
options.extend(['-c', 'copy'])
for (name, value) in metadata.items():
options.extend(['-metadata', '%s=%s' % (name, value)])
chapters = info.get('chapters', [])
if chapters:
metadata_filename = replace_extension(filename, 'meta')
with io.open(metadata_filename, 'wt', encoding='utf-8') as f:
def ffmpeg_escape(text):
return re.sub(r'(=|;|#|\\|\n)', r'\\\1', text)
metadata_file_content = ';FFMETADATA1\n'
for chapter in chapters:
metadata_file_content += '[CHAPTER]\nTIMEBASE=1/1000\n'
metadata_file_content += 'START=%d\n' % (chapter['start_time'] * 1000)
metadata_file_content += 'END=%d\n' % (chapter['end_time'] * 1000)
chapter_title = chapter.get('title')
if chapter_title:
metadata_file_content += 'title=%s\n' % ffmpeg_escape(chapter_title)
f.write(metadata_file_content)
in_filenames.append(metadata_filename)
options.extend(['-map_metadata', '1'])
self._downloader.to_screen('[ffmpeg] Adding metadata to \'%s\'' % filename)
self.run_ffmpeg_multiple_files(in_filenames, temp_filename, options)
if chapters:
os.remove(metadata_filename)
os.remove(encodeFilename(filename))
os.rename(encodeFilename(temp_filename), encodeFilename(filename))
return [], info
class FFmpegMergerPP(FFmpegPostProcessor): class FFmpegMergerPP(FFmpegPostProcessor):
def run(self, info): def run(self, info):