各种弹幕版本的转换
Table of Contents
目前还是在借用许多人的工具,希望以后可以自己整合一下。
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("&","&").replace("<","<").replace(">",">").replace("\"",""").replace("\'","'")
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("&","&").replace("<","<").replace(">",">").replace("\"",""").replace("\'","'"))
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("<", "<") # 小なりの記号。タグを表記したいときにも必要
text = text.replace(">", ">") # 大なりの記号。タグを表記したいときにも必要
text = text.replace("&", "&") # アンパサンド。実体参照で使うため、記号として表示するときに必要
text = text.replace(" ", " ") # ノーブレークスペース
text = text.replace(" ", " ") # フォントサイズの半分のスペース
text = text.replace(" ", " ") # フォントサイズのスペース
text = text.replace("–", "-") # フォントサイズ半分のダッシュ
text = text.replace("—", "-") # フォントサイズのダッシュ
text = text.replace("'","'")
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
Licensed under CC BY-NC-SA 4.0