From a7cacbca2b140f668785d57264914de5585ed699 Mon Sep 17 00:00:00 2001 From: mcd1992 Date: Fri, 22 Aug 2014 16:40:43 -0500 Subject: [PATCH 1/3] Implemented --exec option. --- README.md | 2 + youtube_dl/.__init__.py.swp | Bin 0 -> 16384 bytes youtube_dl/__init__.py | 15 +++++++- youtube_dl/postprocessor/__init__.py | 2 + youtube_dl/postprocessor/execafterdownload.py | 36 ++++++++++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 youtube_dl/.__init__.py.swp create mode 100644 youtube_dl/postprocessor/execafterdownload.py diff --git a/README.md b/README.md index ba9fec8a7..30bdac189 100644 --- a/README.md +++ b/README.md @@ -288,6 +288,8 @@ which means you can modify it, redistribute it or use it however you like. postprocessors (default) --prefer-ffmpeg Prefer ffmpeg over avconv for running the postprocessors + --exec Execute a command after the file is finished downloading, similar to find's -exec format + Example: --exec 'adb push {} /sdcard/Music/ && rm {}' # CONFIGURATION diff --git a/youtube_dl/.__init__.py.swp b/youtube_dl/.__init__.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..0586277fd44037e92b86628697b8bfb898bfe32a GIT binary patch literal 16384 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 Implemented --exec option. ) __license__ = 'Public Domain' @@ -119,6 +123,7 @@ from .postprocessor import ( FFmpegExtractAudioPP, FFmpegEmbedSubtitlePP, XAttrMetadataPP, + ExecAfterDownload, ) @@ -550,7 +555,8 @@ def parseOpts(overrideArguments=None): help='Prefer avconv over ffmpeg for running the postprocessors (default)') postproc.add_option('--prefer-ffmpeg', action='store_true', dest='prefer_ffmpeg', help='Prefer ffmpeg over avconv for running the postprocessors') - + postproc.add_option('--exec', metavar='', action='store', dest='execstring', + help='Execute a command on the file after downloading, similar to find\'s -exec syntax. Must be enclosed in quotes. Example: --exec \'adb push {} /sdcard/Music/ && rm {}\'' ) parser.add_option_group(general) parser.add_option_group(selection) @@ -831,6 +837,7 @@ def _real_main(argv=None): 'default_search': opts.default_search, 'youtube_include_dash_manifest': opts.youtube_include_dash_manifest, 'encoding': opts.encoding, + 'execstring': opts.execstring, } with YoutubeDL(ydl_opts) as ydl: @@ -854,6 +861,12 @@ def _real_main(argv=None): ydl.add_post_processor(FFmpegAudioFixPP()) ydl.add_post_processor(AtomicParsleyPP()) + + # Please keep ExecAfterDownload towards the bottom as it allows the user to modify the final file in any way. + # So if the user is able to remove the file before your postprocessor runs it might cause a few problems. + if opts.execstring: + ydl.add_post_processor(ExecAfterDownload(commandString=opts.execstring)) + # Update version if opts.update_self: update_self(ydl.to_screen, opts.verbose) diff --git a/youtube_dl/postprocessor/__init__.py b/youtube_dl/postprocessor/__init__.py index 08e6ddd00..59ab49e6d 100644 --- a/youtube_dl/postprocessor/__init__.py +++ b/youtube_dl/postprocessor/__init__.py @@ -9,6 +9,7 @@ from .ffmpeg import ( FFmpegEmbedSubtitlePP, ) from .xattrpp import XAttrMetadataPP +from .execafterdownload import ExecAfterDownload __all__ = [ 'AtomicParsleyPP', @@ -19,4 +20,5 @@ __all__ = [ 'FFmpegExtractAudioPP', 'FFmpegEmbedSubtitlePP', 'XAttrMetadataPP', + 'ExecAfterDownload', ] diff --git a/youtube_dl/postprocessor/execafterdownload.py b/youtube_dl/postprocessor/execafterdownload.py new file mode 100644 index 000000000..431ab7f08 --- /dev/null +++ b/youtube_dl/postprocessor/execafterdownload.py @@ -0,0 +1,36 @@ +# ExecAfterDownload written by AaronM / mcd1992. +# If there are any issues with this postprocessor please contact me via github or admin@fgthou.se + +import os, re, shlex +from ..utils import PostProcessingError + +class ExecAfterDownload( object ): + _downloader = None + + def __init__( self, downloader = None, commandString = None ): + self._downloader = downloader + self.commandString = commandString + + def set_downloader( self, downloader ): + """Sets the downloader for this PP.""" + self._downloader = downloader + + def run( self, information ): + self.targetFile = information["filepath"] + self.finalCommand = None; + + if( re.search( '{}', self.commandString ) ): # Find and replace all occurrences of {} with the file name. + self.finalCommand = re.sub( "{}", '\'' + self.targetFile + '\'', self.commandString ) + else: + self.finalCommand = self.commandString + ' \'' + self.targetFile + '\'' + + if( self.finalCommand ): + print( "[exec] Executing command: " + self.finalCommand ) + os.system( self.finalCommand ) + else: + raise PostProcessingExecError( "Invalid syntax for --exec post processor" ) + + return None, information # by default, keep file and do nothing + +class PostProcessingExecError( PostProcessingError ): + pass From a2360a4c80700824f4160505fcdb1ca14261c031 Mon Sep 17 00:00:00 2001 From: mcd1992 Date: Sat, 23 Aug 2014 14:30:13 -0500 Subject: [PATCH 2/3] Moved from os.system to subprocess.call --- .gitignore | 1 + youtube_dl/.__init__.py.swp | Bin 16384 -> 0 bytes youtube_dl/__init__.py | 4 +- youtube_dl/postprocessor/__init__.py | 4 +- youtube_dl/postprocessor/execafterdownload.py | 51 +++++++++--------- 5 files changed, 32 insertions(+), 28 deletions(-) delete mode 100644 youtube_dl/.__init__.py.swp diff --git a/.gitignore b/.gitignore index 37b2fa8d3..b8128fab1 100644 --- a/.gitignore +++ b/.gitignore @@ -26,5 +26,6 @@ updates_key.pem *.m4a *.m4v *.part +*.swp test/testdata .tox diff --git a/youtube_dl/.__init__.py.swp b/youtube_dl/.__init__.py.swp deleted file mode 100644 index 0586277fd44037e92b86628697b8bfb898bfe32a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 z Date: Sun, 24 Aug 2014 15:04:50 -0500 Subject: [PATCH 3/3] Rebased with upstream/master --- README.md | 2 -- youtube_dl/__init__.py | 3 --- 2 files changed, 5 deletions(-) diff --git a/README.md b/README.md index 30bdac189..ba9fec8a7 100644 --- a/README.md +++ b/README.md @@ -288,8 +288,6 @@ which means you can modify it, redistribute it or use it however you like. postprocessors (default) --prefer-ffmpeg Prefer ffmpeg over avconv for running the postprocessors - --exec Execute a command after the file is finished downloading, similar to find's -exec format - Example: --exec 'adb push {} /sdcard/Music/ && rm {}' # CONFIGURATION diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 4eae88d6c..7cf5de43f 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -71,12 +71,9 @@ __authors__ = ( 'Sebastian Haas', 'Alexander Kirk', 'Erik Johnson', -<<<<<<< HEAD 'Keith Beckman', 'Ole Ernst', -======= 'Aaron McDaniel (mcd1992)', ->>>>>>> Implemented --exec option. ) __license__ = 'Public Domain'