1
0
mirror of https://github.com/yt-dlp/yt-dlp.git synced 2024-12-23 04:37:58 +01:00

[embedthumbnail] Correctly escape filename

Closes #352
The approach in [1] is faulty as can be seen in the test cases
1. bff857a8af
This commit is contained in:
pukkandan 2021-05-29 01:39:07 +05:30
parent 885cc0b75c
commit 337e0c62f8
No known key found for this signature in database
GPG Key ID: 0F00D95A001F4698
5 changed files with 75 additions and 56 deletions

85
.gitignore vendored
View File

@ -1,3 +1,46 @@
# Config
*.conf
*.spec
cookies
cookies.txt
# Downloaded
*.srt
*.ttml
*.sbv
*.vtt
*.flv
*.mp4
*.m4a
*.m4v
*.mp3
*.3gp
*.webm
*.wav
*.ape
*.mkv
*.swf
*.part
*.part-*
*.ytdl
*.dump
*.frag
*.frag.urls
*.aria2
*.swp
*.ogg
*.opus
*.info.json
*.live_chat.json
*.jpg
*.png
*.webp
*.annotations.xml
*.description
# Allow config/media files in testdata
!test/testdata/**
# Python # Python
*.pyc *.pyc
*.pyo *.pyo
@ -43,48 +86,6 @@ README.txt
yt-dlp.zip yt-dlp.zip
*.exe *.exe
# Downloaded
*.srt
*.ttml
*.sbv
*.vtt
*.flv
*.mp4
*.m4a
*.m4v
*.mp3
*.3gp
*.webm
*.wav
*.ape
*.mkv
*.swf
*.part
*.part-*
*.ytdl
*.dump
*.frag
*.frag.urls
*.aria2
*.swp
*.ogg
*.opus
*.info.json
*.live_chat.json
*.jpg
*.png
*.webp
*.annotations.xml
*.description
# Config
*.conf
*.spec
cookies
cookies.txt
# Text Editor / IDE # Text Editor / IDE
.idea .idea
*.iml *.iml

View File

@ -8,7 +8,11 @@ import sys
import unittest import unittest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from yt_dlp.postprocessor import MetadataFromFieldPP, MetadataFromTitlePP from yt_dlp.postprocessor import (
FFmpegThumbnailsConvertorPP,
MetadataFromFieldPP,
MetadataFromTitlePP,
)
class TestMetadataFromField(unittest.TestCase): class TestMetadataFromField(unittest.TestCase):
@ -30,3 +34,24 @@ class TestMetadataFromTitle(unittest.TestCase):
def test_format_to_regex(self): def test_format_to_regex(self):
pp = MetadataFromTitlePP(None, '%(title)s - %(artist)s') pp = MetadataFromTitlePP(None, '%(title)s - %(artist)s')
self.assertEqual(pp._titleregex, r'(?P<title>.+)\ \-\ (?P<artist>.+)') self.assertEqual(pp._titleregex, r'(?P<title>.+)\ \-\ (?P<artist>.+)')
class TestConvertThumbnail(unittest.TestCase):
def test_escaping(self):
pp = FFmpegThumbnailsConvertorPP()
if not pp.available:
print('Skipping: ffmpeg not found')
return
file = 'test/testdata/thumbnails/foo %d bar/foo_%d.{}'
tests = (('webp', 'png'), ('png', 'jpg'))
for inp, out in tests:
out_file = file.format(out)
if os.path.exists(out_file):
os.remove(out_file)
pp.convert_thumbnail(file.format(inp), out)
assert os.path.exists(out_file)
for _, out in tests:
os.remove(file.format(out))

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -70,7 +70,7 @@ class EmbedThumbnailPP(FFmpegPostProcessor):
self.to_screen('There aren\'t any thumbnails to embed') self.to_screen('There aren\'t any thumbnails to embed')
return [], info return [], info
idx = next((-(i+1) for i, t in enumerate(info['thumbnails'][::-1]) if t.get('filepath')), None) idx = next((-i for i, t in enumerate(info['thumbnails'][::-1], 1) if t.get('filepath')), None)
if idx is None: if idx is None:
self.to_screen('There are no thumbnails on disk') self.to_screen('There are no thumbnails on disk')
return [], info return [], info

View File

@ -853,19 +853,12 @@ class FFmpegThumbnailsConvertorPP(FFmpegPostProcessor):
return [] return []
def convert_thumbnail(self, thumbnail_filename, target_ext): def convert_thumbnail(self, thumbnail_filename, target_ext):
# NB: % is supposed to be escaped with %% but this does not work
# for input files so working around with standard substitution
escaped_thumbnail_filename = thumbnail_filename.replace('%', '#')
os.rename(encodeFilename(thumbnail_filename), encodeFilename(escaped_thumbnail_filename))
escaped_thumbnail_conv_filename = replace_extension(escaped_thumbnail_filename, target_ext)
self.to_screen('Converting thumbnail "%s" to %s' % (escaped_thumbnail_filename, target_ext))
self.run_ffmpeg(escaped_thumbnail_filename, escaped_thumbnail_conv_filename, self._options(target_ext))
# Rename back to unescaped
thumbnail_conv_filename = replace_extension(thumbnail_filename, target_ext) thumbnail_conv_filename = replace_extension(thumbnail_filename, target_ext)
os.rename(encodeFilename(escaped_thumbnail_filename), encodeFilename(thumbnail_filename))
os.rename(encodeFilename(escaped_thumbnail_conv_filename), encodeFilename(thumbnail_conv_filename)) self.to_screen('Converting thumbnail "%s" to %s' % (thumbnail_filename, target_ext))
self.real_run_ffmpeg(
[(thumbnail_filename, ['-f', 'image2', '-pattern_type', 'none'])],
[(thumbnail_conv_filename.replace('%', '%%'), self._options(target_ext))])
return thumbnail_conv_filename return thumbnail_conv_filename
def run(self, info): def run(self, info):