From ed1694999c5d4e9a8bde780ac244b7b3655d13ac Mon Sep 17 00:00:00 2001 From: Star Brilliant Date: Thu, 18 Oct 2018 18:22:21 +0800 Subject: [PATCH 1/8] Fix issue #44 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5aff166..aa985c0 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ all: install: $(MKDIR) "$(DESTDIR)$(PREFIX)/share/danmaku2ass" - $(INSTALL) -Dm0755 danmaku2ass.py "$(DESTDIR)$(PREFIX)/share/danmaku2ass/danmaku2ass.py" + $(INSTALL) -m0755 danmaku2ass.py "$(DESTDIR)$(PREFIX)/share/danmaku2ass/danmaku2ass.py" for locale in en ja zh_CN zh_TW; do \ $(MKDIR) "$(DESTDIR)$(PREFIX)/share/locale/$$locale/LC_MESSAGES" ; \ $(CP) "po/$$locale.mo" "$(DESTDIR)$(PREFIX)/share/locale/$$locale/LC_MESSAGES/danmaku2ass.mo" ; \ From bb8f1cee060dc1c7e6426159ebadbdb05bf8e901 Mon Sep 17 00:00:00 2001 From: Chaigidel Date: Mon, 24 Feb 2020 18:43:40 +0800 Subject: [PATCH 2/8] support filters in json --- danmaku2ass.py | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/danmaku2ass.py b/danmaku2ass.py index 67e7348..8a0b399 100755 --- a/danmaku2ass.py +++ b/danmaku2ass.py @@ -512,7 +512,7 @@ def ConvertFlashRotation(rotY, rotZ, X, Y, width, height): return (trX, trY, WrapAngle(outX), WrapAngle(outY), WrapAngle(outZ), scaleXY * 100, scaleXY * 100) -def ProcessComments(comments, f, width, height, bottomReserved, fontface, fontsize, alpha, duration_marquee, duration_still, filter_regex, reduced, progress_callback): +def ProcessComments(comments, f, width, height, bottomReserved, fontface, fontsize, alpha, duration_marquee, duration_still, filters_regex, reduced, progress_callback): styleid = 'Danmaku2ASS_%04x' % random.randint(0, 0xffff) WriteASSHead(f, width, height, fontface, fontsize, alpha, styleid) rows = [[None] * (height - bottomReserved + 1) for i in range(4)] @@ -520,7 +520,12 @@ def ProcessComments(comments, f, width, height, bottomReserved, fontface, fontsi if progress_callback and idx % 1000 == 0: progress_callback(idx, len(comments)) if isinstance(i[4], int): - if filter_regex and filter_regex.search(i[3]): + skip = False + for filter_regex in filters_regex: + if filter_regex and filter_regex.search(i[3]): + skip = True + break + if skip: continue row = 0 rowmax = height - bottomReserved - i[7] @@ -726,14 +731,18 @@ def export(func): @export -def Danmaku2ASS(input_files, input_format, output_file, stage_width, stage_height, reserve_blank=0, font_face=_('(FONT) sans-serif')[7:], font_size=25.0, text_opacity=1.0, duration_marquee=5.0, duration_still=5.0, comment_filter=None, is_reduce_comments=False, progress_callback=None): - try: - if comment_filter: - filter_regex = re.compile(comment_filter) - else: - filter_regex = None - except: - raise ValueError(_('Invalid regular expression: %s') % comment_filter) +def Danmaku2ASS(input_files, input_format, output_file, stage_width, stage_height, reserve_blank=0, font_face=_('(FONT) sans-serif')[7:], font_size=25.0, text_opacity=1.0, duration_marquee=5.0, duration_still=5.0, comment_filter=None, comment_filters_json=None, is_reduce_comments=False, progress_callback=None): + comment_filters = [comment_filter] + if comment_filters_json: + with open(comment_filters_json, 'r') as f: + comment_filters.extend(json.load(f)) + filters_regex = [] + for comment_filter in comment_filters: + try: + if comment_filter: + filters_regex.append(re.compile(comment_filter)) + except: + raise ValueError(_('Invalid regular expression: %s') % comment_filter) fo = None comments = ReadComments(input_files, input_format, font_size) try: @@ -741,7 +750,7 @@ def Danmaku2ASS(input_files, input_format, output_file, stage_width, stage_heigh fo = ConvertToFile(output_file, 'w', encoding='utf-8-sig', errors='replace', newline='\r\n') else: fo = sys.stdout - ProcessComments(comments, fo, stage_width, stage_height, reserve_blank, font_face, font_size, text_opacity, duration_marquee, duration_still, filter_regex, is_reduce_comments, progress_callback) + ProcessComments(comments, fo, stage_width, stage_height, reserve_blank, font_face, font_size, text_opacity, duration_marquee, duration_still, filters_regex, is_reduce_comments, progress_callback) finally: if output_file and fo != output_file: fo.close() @@ -800,6 +809,7 @@ def main(): parser.add_argument('-dm', '--duration-marquee', metavar=_('SECONDS'), help=_('Duration of scrolling comment display [default: %s]') % 5, type=float, default=5.0) parser.add_argument('-ds', '--duration-still', metavar=_('SECONDS'), help=_('Duration of still comment display [default: %s]') % 5, type=float, default=5.0) parser.add_argument('-fl', '--filter', help=_('Regular expression to filter comments')) + parser.add_argument('-flf', '--filter-file', help=_('Regular expressions from json file to filter comments')) parser.add_argument('-p', '--protect', metavar=_('HEIGHT'), help=_('Reserve blank on the bottom of the stage'), type=int, default=0) parser.add_argument('-r', '--reduce', action='store_true', help=_('Reduce the amount of comments if stage is full')) parser.add_argument('file', metavar=_('FILE'), nargs='+', help=_('Comment file to be processed')) @@ -810,7 +820,7 @@ def main(): height = int(height) except ValueError: raise ValueError(_('Invalid stage size: %r') % args.size) - Danmaku2ASS(args.file, args.format, args.output, width, height, args.protect, args.font, args.fontsize, args.alpha, args.duration_marquee, args.duration_still, args.filter, args.reduce) + Danmaku2ASS(args.file, args.format, args.output, width, height, args.protect, args.font, args.fontsize, args.alpha, args.duration_marquee, args.duration_still, args.filter, args.filter_file, args.reduce) if __name__ == '__main__': From ce41af1468f4bf012b4f5f32b816b96608861bab Mon Sep 17 00:00:00 2001 From: Chaigidel Date: Mon, 24 Feb 2020 18:52:39 +0800 Subject: [PATCH 3/8] readable help --- README.md | 2 ++ danmaku2ass.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b5191f9..b968a55 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,8 @@ optional arguments: Duration of still comment display [default: 5] -fl FILTER, --filter FILTER Regular expression to filter comments + -flf FILTER_FILE, --filter-file FILTER_FILE + Regular expressions from json file (contain a regex list) to filter comments -p HEIGHT, --protect HEIGHT Reserve blank on the bottom of the stage -r, --reduce Reduce the amount of comments if stage is full diff --git a/danmaku2ass.py b/danmaku2ass.py index 8a0b399..e8f4ce0 100755 --- a/danmaku2ass.py +++ b/danmaku2ass.py @@ -809,7 +809,7 @@ def main(): parser.add_argument('-dm', '--duration-marquee', metavar=_('SECONDS'), help=_('Duration of scrolling comment display [default: %s]') % 5, type=float, default=5.0) parser.add_argument('-ds', '--duration-still', metavar=_('SECONDS'), help=_('Duration of still comment display [default: %s]') % 5, type=float, default=5.0) parser.add_argument('-fl', '--filter', help=_('Regular expression to filter comments')) - parser.add_argument('-flf', '--filter-file', help=_('Regular expressions from json file to filter comments')) + parser.add_argument('-flf', '--filter-file', help=_('Regular expressions from json file (contain a regex list) to filter comments')) parser.add_argument('-p', '--protect', metavar=_('HEIGHT'), help=_('Reserve blank on the bottom of the stage'), type=int, default=0) parser.add_argument('-r', '--reduce', action='store_true', help=_('Reduce the amount of comments if stage is full')) parser.add_argument('file', metavar=_('FILE'), nargs='+', help=_('Comment file to be processed')) From 1add7b3b52bfcc821625c7ccb9c4d4a7303827d4 Mon Sep 17 00:00:00 2001 From: Chaigidel Date: Mon, 24 Feb 2020 23:00:10 +0800 Subject: [PATCH 4/8] simplify --- README.md | 2 +- danmaku2ass.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b968a55..a1f7e10 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ optional arguments: -fl FILTER, --filter FILTER Regular expression to filter comments -flf FILTER_FILE, --filter-file FILTER_FILE - Regular expressions from json file (contain a regex list) to filter comments + Regular expressions from file (one line one regex) to filter comments -p HEIGHT, --protect HEIGHT Reserve blank on the bottom of the stage -r, --reduce Reduce the amount of comments if stage is full diff --git a/danmaku2ass.py b/danmaku2ass.py index e8f4ce0..f9043c2 100755 --- a/danmaku2ass.py +++ b/danmaku2ass.py @@ -735,7 +735,8 @@ def Danmaku2ASS(input_files, input_format, output_file, stage_width, stage_heigh comment_filters = [comment_filter] if comment_filters_json: with open(comment_filters_json, 'r') as f: - comment_filters.extend(json.load(f)) + d = f.readlines() + comment_filters.extend([i.strip() for i in d]) filters_regex = [] for comment_filter in comment_filters: try: @@ -809,7 +810,7 @@ def main(): parser.add_argument('-dm', '--duration-marquee', metavar=_('SECONDS'), help=_('Duration of scrolling comment display [default: %s]') % 5, type=float, default=5.0) parser.add_argument('-ds', '--duration-still', metavar=_('SECONDS'), help=_('Duration of still comment display [default: %s]') % 5, type=float, default=5.0) parser.add_argument('-fl', '--filter', help=_('Regular expression to filter comments')) - parser.add_argument('-flf', '--filter-file', help=_('Regular expressions from json file (contain a regex list) to filter comments')) + parser.add_argument('-flf', '--filter-file', help=_('Regular expressions from file (one line one regex) to filter comments')) parser.add_argument('-p', '--protect', metavar=_('HEIGHT'), help=_('Reserve blank on the bottom of the stage'), type=int, default=0) parser.add_argument('-r', '--reduce', action='store_true', help=_('Reduce the amount of comments if stage is full')) parser.add_argument('file', metavar=_('FILE'), nargs='+', help=_('Comment file to be processed')) From 4c4de516a1f1d14aca4e41f80b1ed553da6ee344 Mon Sep 17 00:00:00 2001 From: Chaigidel Date: Tue, 25 Feb 2020 00:01:11 +0800 Subject: [PATCH 5/8] change arg name --- danmaku2ass.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/danmaku2ass.py b/danmaku2ass.py index f9043c2..1eb91d4 100755 --- a/danmaku2ass.py +++ b/danmaku2ass.py @@ -731,10 +731,10 @@ def export(func): @export -def Danmaku2ASS(input_files, input_format, output_file, stage_width, stage_height, reserve_blank=0, font_face=_('(FONT) sans-serif')[7:], font_size=25.0, text_opacity=1.0, duration_marquee=5.0, duration_still=5.0, comment_filter=None, comment_filters_json=None, is_reduce_comments=False, progress_callback=None): +def Danmaku2ASS(input_files, input_format, output_file, stage_width, stage_height, reserve_blank=0, font_face=_('(FONT) sans-serif')[7:], font_size=25.0, text_opacity=1.0, duration_marquee=5.0, duration_still=5.0, comment_filter=None, comment_filters_file=None, is_reduce_comments=False, progress_callback=None): comment_filters = [comment_filter] - if comment_filters_json: - with open(comment_filters_json, 'r') as f: + if comment_filters_file: + with open(comment_filters_file, 'r') as f: d = f.readlines() comment_filters.extend([i.strip() for i in d]) filters_regex = [] From 0925edeb17431954bdf14954b90c93f7b0fd0109 Mon Sep 17 00:00:00 2001 From: XZiar Date: Thu, 6 May 2021 20:38:57 -0700 Subject: [PATCH 6/8] add basic support for bilibili's version2.0 xml --- danmaku2ass.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/danmaku2ass.py b/danmaku2ass.py index 1eb91d4..4e8d1e0 100755 --- a/danmaku2ass.py +++ b/danmaku2ass.py @@ -74,6 +74,8 @@ def ProbeCommentFormat(f): return 'Niconico' elif tmp == 'xml version="1.0" encoding="UTF-8"?>\n<': @@ -194,6 +196,30 @@ def ReadCommentsBilibili(f, fontsize): continue +def ReadCommentsBilibili2(f, fontsize): + dom = xml.dom.minidom.parse(f) + comment_element = dom.getElementsByTagName('d') + for i, comment in enumerate(comment_element): + try: + p = str(comment.getAttribute('p')).split(',') + assert len(p) >= 7 + assert p[3] in ('1', '4', '5', '6', '7', '8') + if comment.childNodes.length > 0: + time = float(p[2]) / 1000.0 + if p[3] in ('1', '4', '5', '6'): + c = str(comment.childNodes[0].wholeText).replace('/n', '\n') + size = int(p[4]) * fontsize / 25.0 + yield (time, int(p[6]), i, c, {'1': 0, '4': 2, '5': 1, '6': 3}[p[3]], int(p[5]), size, (c.count('\n') + 1) * size, CalculateLength(c) * size) + elif p[3] == '7': # positioned comment + c = str(comment.childNodes[0].wholeText) + yield (time, int(p[6]), i, c, 'bilipos', int(p[5]), int(p[4]), 0, 0) + elif p[3] == '8': + pass # ignore scripted comment + except (AssertionError, AttributeError, IndexError, TypeError, ValueError): + logging.warning(_('Invalid comment: %s') % comment.toxml()) + continue + + def ReadCommentsTudou(f, fontsize): comment_element = json.load(f) for i, comment in enumerate(comment_element['comment_list']): @@ -244,7 +270,7 @@ def ReadCommentsMioMio(f, fontsize): continue -CommentFormatMap = {'Niconico': ReadCommentsNiconico, 'Acfun': ReadCommentsAcfun, 'Bilibili': ReadCommentsBilibili, 'Tudou': ReadCommentsTudou, 'Tudou2': ReadCommentsTudou2, 'MioMio': ReadCommentsMioMio} +CommentFormatMap = {'Niconico': ReadCommentsNiconico, 'Acfun': ReadCommentsAcfun, 'Bilibili': ReadCommentsBilibili, 'Bilibili2': ReadCommentsBilibili2, 'Tudou': ReadCommentsTudou, 'Tudou2': ReadCommentsTudou2, 'MioMio': ReadCommentsMioMio} def WriteCommentBilibiliPositioned(f, c, width, height, styleid): From b53fc11b379b664ecdc486e60aea5876480c142b Mon Sep 17 00:00:00 2001 From: uohlhv Date: Sat, 13 Nov 2021 09:49:53 +0800 Subject: [PATCH 7/8] Fix errors occured when the attribute 'no' doesn't exist --- danmaku2ass.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/danmaku2ass.py b/danmaku2ass.py index 4e8d1e0..4b6563c 100755 --- a/danmaku2ass.py +++ b/danmaku2ass.py @@ -144,7 +144,7 @@ def ReadCommentsNiconico(f, fontsize): size = fontsize * 0.64 elif mailstyle in NiconicoColorMap: color = NiconicoColorMap[mailstyle] - yield (max(int(comment.getAttribute('vpos')), 0) * 0.01, int(comment.getAttribute('date')), int(comment.getAttribute('no')), c, pos, color, size, (c.count('\n') + 1) * size, CalculateLength(c) * size) + yield (max(int(comment.getAttribute('vpos')), 0) * 0.01, int(comment.getAttribute('date')), 0, c, pos, color, size, (c.count('\n') + 1) * size, CalculateLength(c) * size) except (AssertionError, AttributeError, IndexError, TypeError, ValueError): logging.warning(_('Invalid comment: %s') % comment.toxml()) continue From 7453e571fc4ad5835634e6031f93085b6fdb150e Mon Sep 17 00:00:00 2001 From: uohlhv Date: Mon, 30 Jun 2025 00:04:53 +0800 Subject: [PATCH 8/8] Fix ass syntax --- danmaku2ass.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/danmaku2ass.py b/danmaku2ass.py index 4b6563c..0329055 100755 --- a/danmaku2ass.py +++ b/danmaku2ass.py @@ -397,7 +397,7 @@ def WriteCommentAcfunPositioned(f, c, width, height, styleid): try: comment_args = c[3] text = ASSEscape(str(comment_args['n']).replace('\r', '\n')) - common_styles = ['\org(%d, %d)' % (width / 2, height / 2)] + common_styles = ['\\org(%d, %d)' % (width / 2, height / 2)] anchor = {0: 7, 1: 8, 2: 9, 3: 4, 4: 5, 5: 6, 6: 1, 7: 2, 8: 3}.get(comment_args.get('c', 0), 7) if anchor != 7: common_styles.append('\\an%s' % anchor)