目前还是在借用许多人的工具,希望以后可以自己整合一下。

ASOBISTAGE#

使用的是ascomments-dl

首先是用ascomments-dl.py,将录播的弹幕保存为json

import asyncio
import websockets
import sys
import re
import os

count = 10000

args = sys.argv
pageurl = args[1]

def extract_info_from_url(pageurl):
    pattern = r"https://asobistage.asobistore.jp/event/([^/]+)/archive/([^/]+)"
    match = re.match(pattern, pageurl)
    if match:
        eventname = match.group(1)
        day = match.group(2)
        return eventname, day
    else:
        raise ValueError("Invalid URL format\nUsage:ascomments-dl [ASOBISTAGE LIVE Archive Page URL]")

async def download():
    print("Connecting comment server (archive) via WebSocket...")
    async with websockets.connect(uri) as websocket:
        await websocket.recv()
        nonecount=0
        for i in range(count):
            sendtxt="{\"func\":\"archive-get\",\"time\":\""+str(5*i)+"\"}"
            await websocket.send(sendtxt)
            comment=await websocket.recv()
            comment_nakami=comment[12:-2]

            if i>0 and len(comment_nakami)!=0:
                f.write(",")

            f.write(str(comment_nakami))

            

            if len(comment_nakami)==0:
                nonecount=nonecount+1
            else:
                nonecount=0
            if nonecount>19:
                break

            print("Downloading... Count:",i,"Sending:",sendtxt,"Empty:",nonecount, end="\r", flush=True)

        print()
        print("Closing and Saving...")

print("This is a software that downloads comments from ASOBISTAGE's broadcast live archives.")
print("The page URL is ",pageurl)
eventname, day = extract_info_from_url(pageurl)
uri = "wss://replay.asobistore.jp/"+eventname+"_"+day+"_ch1/archive"

print("Downloading from ",uri)

filename=eventname+"_"+day+"_comments.json"

if os.path.exists(filename):
    overwrite = input("File already exists. Do you want to overwrite it? (y/N): ")
    if overwrite.lower() == "y":
        print("Overwriting", filename)
        with open(filename, 'w', encoding='UTF-8') as f:
            f.write("[")
            asyncio.run(download())
            f.write("]")
    else:
        print("File not overwritten.")
else:
    print("Saving into", filename)
    with open(filename, 'w', encoding='UTF-8') as f:
        f.write("[")
        asyncio.run(download())
        f.write("]")

接着是asobi2nico.py,将json转为nico的xml形式

import json
import sys
import datetime
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN

print("Converting ASOBISTAGE comments json to niconico comments xml...")
args = sys.argv
filename=str(args[1])
json_file = open(filename, 'r', encoding='UTF-8')
f = open(filename+".xml", 'x', encoding='UTF-8')

f.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<packet>\n")

json_object = json.load(json_file)

for i in range(len(json_object)):
    f.write("<chat thread=\"\" no=\""+str(i+1)+"\" ")

    #vpos変換
    vpos=str(Decimal(str(float(json_object[i]['playtime'])*100)).quantize(Decimal('0'), rounding=ROUND_HALF_UP))
    f.write("vpos=\""+vpos+"\" ")

    #日時変換
    dte = datetime.datetime.strptime(str(json_object[i]['time'])[:-3], '%Y-%m-%d %H:%M:%S.%f')
    date=int(dte.timestamp())

    username=str(json_object[i]['data']['userName']).replace("\\u3000"," ").replace("&","&amp;").replace("<","&lt;").replace(">","&gt;").replace("\"","&quot;").replace("\'","&apos;")

    f.write("date=\""+str(date)+"\" mail=\"184\" user_id=\"\" user_name=\""+username+"\" user_color=\""+str(json_object[i]['data']['color'])+"\" anonymity=\"1\" ")

    f.write("date_usec=\""+dte.strftime('%f')+"\">")

    f.write(str(json_object[i]['data']['comment'])[2:-2].replace("\\u3000"," ").replace("&","&amp;").replace("<","&lt;").replace(">","&gt;").replace("\"","&quot;").replace("\'","&apos;"))
    f.write("</chat>\n")

f.write("</packet>")

Youtube Live#

通过yt-dlp下载json文件

yt-dlp --skip-download --write-subs https://www.youtube.com/watch?v=eA5iPy7sRpw

使用convert_chat_to_xml.py,转为xml形式

# Convert chat to xml ver1.0.3
# 作者:Bookyakuno
# ウェブサイト:【スクリプト配布】YouTube のチャットファイル(.live_chat.json)をニコニコのコメントのxml形式に変換するスクリプト【Python】 – 忘却まとめ
#        https://bookyakuno.com/convert_youtube_chat_json_to_nico_xml/
#
# Convert youtube chat json to niconicko comment xml.
# YouTube のチャットファイル(.live_chat.json)をニコニコ動画のxml形式に変換する関数
# チャットファイルはyoutube-dlやyt-dlpなどでダウンロードしたものの形式で動きます。
# YouTube のチャットファイルプレイヤーが見つからなかったので、似た機能であるニコニコ動画プレイヤーでチャットを再生できるように変換する関数です。
# ニコニコ動画コメントプレイヤーには commeon などを利用してください。


# ■ 使い方
# コマンドプロンプトで、下記のように実行します。
# 渡されたパスがフォルダーの場合は、フォルダー内のjsonを一括処理します。
# 変換されたxmlファイルは、「xml」フォルダー内に保存されます。
#
# python "C:\Users\<USER_NAME>\Desktop\test\convert_chat_to_xml.py" "C:\Users\<USER_NAME>\Desktop\test\_video190530 - #05【悪魔城ドラキュラ】諦めない心ッ…!!鈴原るるは戦う!【鈴原るる_にじさんじ】 - [Sbh6TXCxs40].live_chat.json"

import datetime, json, sys , os, datetime, re

# 変換したいjsonのファイルパス
target_dir = sys.argv[1]


# jsonファイルの読み込み
def import_json(target_dir):
    path = target_dir
    json_open = open(path, 'r',encoding="utf-8")
    json_load = []
    decoder = json.JSONDecoder()
    with json_open as f:
        line = f.readline()
        while line:
            json_load.append(decoder.raw_decode(line))
            line = f.readline()
    return json_load

# タイムスタンプが0:00のようになっているので、全て秒に変換
def convert_timetext(time_text, user_name, text):
    time_l = time_text.split(":")
    if len(time_l) == 2:
        mini, sec = time_l
        hour = 0
    elif len(time_l) == 3:
        hour, mini, sec = time_l
    try:
        second = (int(hour) * 3600) + (int(mini) * 60) + (int(sec))
    except ValueError:
        print("ValueError  > %s%s」" % (user_name,text))
        return "0"
    time_text = str(second) + "00"
    return time_text


# テキスト内の特殊文字を変換
def replace_text(text):
    text = text.replace("<", "&lt;")    # 小なりの記号。タグを表記したいときにも必要
    text = text.replace(">", "&gt;")    # 大なりの記号。タグを表記したいときにも必要
    text = text.replace("&", "&amp;")    # アンパサンド。実体参照で使うため、記号として表示するときに必要
    text = text.replace(" ", " ")    # ノーブレークスペース
    text = text.replace(" ", " ")    # フォントサイズの半分のスペース
    text = text.replace(" ", " ")    # フォントサイズのスペース
    text = text.replace("–", "-")    # フォントサイズ半分のダッシュ
    text = text.replace("—", "-")    # フォントサイズのダッシュ
    text = text.replace("'","&#039;")
    return text

# さんぷる
# <chat thread="1640883302" no="1" vpos="704" date="1000000012" date_usec="2" anonymity="1" user_id="hR1wp4m-xxIaU2RgsVMr4zPyzeU" mail="184" leaf="0" premium="1" score="0">うぽつですー</chat>


# コア関数
def convert_youtube_chat_json_to_nico_xml(target_dir):
    info_start_time = datetime.datetime.now()

    if os.path.isfile(target_dir):
        path_l = [target_dir]
    else:
        path_l = [os.path.join(target_dir,i) for i in os.listdir(target_dir)]

    for index,target_path in enumerate(path_l):
        if index == 0:
            print("Create 'xml' Folder")
            os.makedirs(os.path.join(os.path.dirname(target_path),"xml"), exist_ok=True)
        if not os.path.splitext(target_path)[1] == ".json":
            continue
        print("file_name",target_path)

        print("==================================")
        print("===> Run > %s" % os.path.basename(target_path))
        print("===> Start Import json")
        json_load = import_json(target_path)
        print("===> Start convert")
        # jsonの必要な情報を整形
        line_l = ["<packet>\n"]
        finished_l = []
        for index, item in enumerate(json_load):
            if not "addChatItemAction" in item[0]['replayChatItemAction']['actions'][0].keys():
                continue
            if not "liveChatTextMessageRenderer" in item[0]['replayChatItemAction']['actions'][0]['addChatItemAction']['item'].keys():
                continue
            render = item[0]['replayChatItemAction']['actions'][0]['addChatItemAction']['item']['liveChatTextMessageRenderer']
            #
            # ユーザーネーム
            if "authorName" in render.keys():
                user_name = render['authorName']['simpleText']
            else:
                user_name = ""
            #
            # テキストを整形(絵文字は別の模様。ここはまだ調整必要)
            text = ""
            if "text" in render['message']['runs'][0].keys():
                text = render['message']['runs'][0]['text']
            if len(render['message']['runs']) > 1 and len(render['message']['runs'][0]) >= 2:
                text += render['message']['runs'][1]['emoji']
            #
            # タイムスタンプ
            time_text = render['timestampText']['simpleText']
            time_text = convert_timetext(time_text, user_name, text)
            line_l += ["<chat vpos='%s' no='%s' user_id='%s'> %s </chat>\n" % (time_text, index , replace_text(user_name), replace_text(text))]
            finished_l += [1]
        #
        print("===> Finished items [%s]" % str(len(finished_l)))
        #
        # ファイルに書き込み
        print("===> Start write xml")
        line_l += ["</packet>"]
        new_path = target_path.replace(".live_chat.json","") + ".xml"
        new_path = os.path.join(os.path.dirname(new_path),"xml",os.path.basename(new_path))
        with open(new_path, mode='w',encoding="utf-8") as f:
            f.writelines(line_l)

        date_o = datetime.datetime.now() - info_start_time
        date_o_l = re.match("^(.+\.)(\d\d)\d\d\d\d$",str(date_o))
        date_o = date_o_l[1] + date_o_l[2]
        print("\n===> __Saved__ [%s]> %s\n\n\n" % (date_o,new_path))

    date_o = datetime.datetime.now() - info_start_time
    date_o_l = re.match("^(.+\.)(\d\d)\d\d\d\d$",str(date_o))
    date_o = date_o_l[1] + date_o_l[2]
    print("All Finished [%s]" % date_o)


# 実行
if __name__ == "__main__":
    convert_youtube_chat_json_to_nico_xml(target_dir)

xml转ass#

目前使用的是nico-danmaku2ass