def subtitles( self, comments: Comments) -> Generator[Tuple[str, Comment], None, None]: """ Subtitle generator :param comments: Comments to turn into subtitles :return: Generator with subtitles and subtitle data """ for index, comment in enumerate(comments): # Stat and stop timestamps. Add a millisecond for timedelta to include millisecond digits start = datetime.timedelta(seconds=comment.content_offset_seconds) stop: datetime.timedelta = start + datetime.timedelta( milliseconds=self.format_dictionary['duration']) # Format message message: str = Pipe(self.format_dictionary['comments']).comment( comment.data) # Subtitle variables # Subtract the last three milliseconds form timestamp (required by SRT) subtitle: dict = { 'index': index + 1, 'start': SRT.format_timestamp(start), 'stop': SRT.format_timestamp(stop), 'message': message } yield '{index}\n{start} --> {stop}\n{message}\n'.format_map( SafeDict(subtitle)), comment
def use(self) -> Tuple[Generator[Tuple[str, Comment], None, None], str]: """ Use SRT format :return: Comment generator and output string """ return self.subtitles(self.video.comments), Pipe( self.format_dictionary['output']).output(self.video.data)
def use(self) -> Tuple[Generator[Tuple[str, Comment], None, None], str]: """ Use SSA format :return: """ output: str = Pipe(self.format_dictionary['output']).output( self.video.data) return self.generator(), output
def use(self) -> Tuple[Generator[Tuple[str, twitch.v5.Comment], None, None], str]: """ Use this format :return: tuple(formatted comment, comment), output format """ # Format comments comments = self.comment_generator(self.video.comments()) # Format output output: str = Pipe(self.format_dictionary['output']).output(self.video.data) return comments, output
def comment_generator( self, comments: Comments) -> Generator[Tuple[str, Comment], None, None]: for comment in comments: yield Pipe(self.format_dictionary['comments']).comment( comment.data), comment
def dialogues( self, comments: Comments) -> Generator[Tuple[str, Comments], None, None]: """ Format comments as SSA dialogues :param comments: Comment to format :return: tuple(formatted comment, comment) """ for comment in comments: start: datetime.timedelta = datetime.timedelta( seconds=comment.content_offset_seconds) end: datetime.timedelta = start + datetime.timedelta( milliseconds=self.format_dictionary['duration']) # Avoid SSA variable conflicts with Python string formatting # This is done by temporarily removing opening and closing curly brackets used by SSA. # # The main problem is detecting these curly brackets. We want to differentiate brackets that # should be used by the Python string formatter, and those used by SSA. # # Opening curly brackets for SSA can easily be found by looking for "{\", however, # closing curly brackets are used in the same way (just a "}") for both and requires a bit more effort. # # By incrementing a counter for opening brackets meant for Python formatting and decrementing for every # closing bracket meant for Python formatting, we can define every closing bracket to belong to SSA whenever # the counter is at zero. ssa_closing_brackets_indices: list = [] open_bracket_counter: int = 0 # Loop through every character in formatting string for index in range( len(self.format_dictionary['comments']['format'])): letter: str = self.format_dictionary['comments']['format'][ index] # Check if SSA bracket first, before altering the counter. if letter is '}' and open_bracket_counter is 0: ssa_closing_brackets_indices.append(index) continue # Update counter open_bracket_counter += { '{': 1, # Bracket is opened '\\': -1, # Bracket was meant for SSA, not for Python '}': -1 # Closing bracket }.get(letter, 0) # Multiple SSA commands within a curly brackets could make it negative # Example: {\\c�&\\b1} will count 1, 0, -1, -2 open_bracket_counter = max(0, open_bracket_counter) # Add a temporary special character for SSA closing curly brackets for index in ssa_closing_brackets_indices: self.format_dictionary['comments']['format'] = self.format_dictionary['comments']['format'][ :index] + SSA.SPECIAL + \ self.format_dictionary['comments']['format'][index + 1:] self.format_dictionary['comments'][ 'format'] = self.format_dictionary['comments'][ 'format'].replace('{\\', SSA.OPEN).replace( SSA.SPECIAL, SSA.CLOSE) # Format comment comment_text = Pipe(self.format_dictionary['comments']).comment( comment.data) # Insert opening and closing curly brackets for SSA comment_text = comment_text.replace(SSA.OPEN, '{\\').replace(SSA.CLOSE, '}') # Convert color code into SSA color code. comment_text = comment_text.replace('\\c&#', '\\c&H').replace( '\\c&H#', '\\c&H') dialogue: dict = { 'start': SSA.format_timestamp(start), 'end': SSA.format_timestamp(end), 'comment': comment_text } dialogue.update(comment.data) yield self.format_dictionary['events']['dialogue'].format_map( SafeDict(dialogue)), comment