]> jfr.im git - yt-dlp.git/blob - youtube_dlc/postprocessor/sponskrub.py
9215913bcad803a36aa3a67f71a57c499fbde061
[yt-dlp.git] / youtube_dlc / postprocessor / sponskrub.py
1 from __future__ import unicode_literals
2 import os
3 import subprocess
4
5 from .common import PostProcessor
6 from ..compat import compat_shlex_split
7 from ..utils import (
8 check_executable,
9 encodeArgument,
10 shell_quote,
11 PostProcessingError,
12 )
13
14
15 class SponSkrubPP(PostProcessor):
16 _temp_ext = 'spons'
17 _def_args = []
18 _exe_name = 'sponskrub'
19
20 def __init__(self, downloader, path='', args=None, ignoreerror=False, cut=False, force=False):
21 PostProcessor.__init__(self, downloader)
22 self.force = force
23 self.cutout = cut
24 self.args = ['-chapter'] if not cut else []
25 self.args += self._configuration_args(self._def_args) if args is None else compat_shlex_split(args)
26 self.path = self.get_exe(path)
27
28 if not ignoreerror and self.path is None:
29 if path:
30 raise PostProcessingError('sponskrub not found in "%s"' % path)
31 else:
32 raise PostProcessingError('sponskrub not found. Please install or provide the path using --sponskrub-path.')
33
34 def get_exe(self, path=''):
35 if not path or not check_executable(path, ['-h']):
36 path = os.path.join(path, self._exe_name)
37 if not check_executable(path, ['-h']):
38 return None
39 return path
40
41 def run(self, information):
42 if self.path is None:
43 return [], information
44
45 if information['extractor_key'].lower() != 'youtube':
46 self.to_screen('Skipping sponskrub since it is not a YouTube video')
47 return [], information
48 if self.cutout and not self.force and not information.get('__real_download', False):
49 self.report_warning(
50 'Skipping sponskrub since the video was already downloaded. '
51 'Use --sponskrub-force to run sponskrub anyway')
52 return [], information
53
54 self.to_screen('Trying to %s sponsor sections' % ('remove' if self.cutout else 'mark'))
55 if self.cutout:
56 self.report_warning('Cutting out sponsor segments will cause the subtitles to go out of sync.')
57 if not information.get('__real_download', False):
58 self.report_warning('If sponskrub is run multiple times, unintended parts of the video could be cut out.')
59
60 filename = information['filepath']
61 temp_filename = filename + '.' + self._temp_ext + os.path.splitext(filename)[1]
62 if os.path.exists(temp_filename):
63 os.remove(temp_filename)
64
65 cmd = [self.path]
66 if self.args:
67 cmd += self.args
68 cmd += ['--', information['id'], filename, temp_filename]
69 cmd = [encodeArgument(i) for i in cmd]
70
71 self.write_debug('sponskrub command line: %s' % shell_quote(cmd))
72 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
73 stdout, stderr = p.communicate()
74
75 if p.returncode == 0:
76 os.remove(filename)
77 os.rename(temp_filename, filename)
78 self.to_screen('Sponsor sections have been %s' % ('removed' if self.cutout else 'marked'))
79 elif p.returncode == 3:
80 self.to_screen('No segments in the SponsorBlock database')
81 else:
82 stderr = stderr.decode('utf-8', 'replace')
83 msg = stderr.strip().split('\n')[-1]
84 raise PostProcessingError(msg if msg else 'sponskrub failed with error code %s!' % p.returncode)
85 return [], information