diff --git a/README.md b/README.md index 9ecfde9..96d5219 100644 --- a/README.md +++ b/README.md @@ -45,10 +45,10 @@ while chat.is_alive(): #other background operation here. time.sleep(3) -def func(chatdata): - for c in chatdata.items: +def func(data): + for c in data.items: print(f"{c.datetime} [{c.author.name}]-{c.message} {c.amountString}") - chat.tick() + data.tick() ``` ### asyncio context: @@ -62,17 +62,17 @@ async def main(): #other background operation here. await asyncio.sleep(3) -async def func(chat) - for c in chat.items: +async def func(data): + for c in data.items: print(f"{c.datetime} [{c.author.name}]-{c.message} {c.amountString}") - await chat.tick_async() + await data.tick_async() loop = asyncio.get_event_loop() loop.run_until_complete(main()) ``` -### yt api compatible processor: +### youtube api compatible processor: ```python from pytchat import LiveChat, CompatibleProcessor @@ -89,7 +89,30 @@ while chat.is_alive(): time.sleep(polling/len(data["items"])) ``` +### replay: +```python +from pytchat import ReplayChatAsync +import asyncio +async def main(): + chat = ReplayChatAsync("G1w62uEMZ74", seektime = 1000, callback = func) + while chat.is_alive(): + #other background operation here. + await asyncio.sleep(3) + +async def func(data): + for count in range(0,len(data.items)): + c= data.items[count] + if count!=len(data.items): + tick=data.items[count+1].timestamp -data.items[count].timestamp + else: + tick=0 + print(f"<{c.timestampText}> [{c.author.name}]-{c.message} {c.amountString}") + await asyncio.sleep(tick/1000) + +loop = asyncio.get_event_loop() +loop.run_until_complete(main()) +``` ## Chatdata Structure of Default Processor Structure of each item which got from items() function. @@ -122,7 +145,11 @@ Structure of each item which got from items() function. datetime str - + ex. "2019-10-10 12:34:56" + + timestampText + str + elapsed time. (ex. "1:02:27") amountValue @@ -137,7 +164,7 @@ Structure of each item which got from items() function. currency str - ISO 4217 currency codes (ex. "USD") + ISO 4217 currency codes (ex. "USD") bgColor @@ -175,12 +202,12 @@ Structure of author object. imageUrl - + str badgeUrl - + str diff --git a/pytchat/__init__.py b/pytchat/__init__.py index 60da97f..e9bbe15 100644 --- a/pytchat/__init__.py +++ b/pytchat/__init__.py @@ -1,8 +1,8 @@ """ -pytchat is a python library for fetching youtube live chat. +pytchat is a python library for fetching youtube live chat without using yt api, Selenium, or BeautifulSoup. """ __copyright__ = 'Copyright (C) 2019 taizan-hokuto' -__version__ = '0.0.2.3' +__version__ = '0.0.3.0' __license__ = 'MIT' __author__ = 'taizan-hokuto' __author_email__ = '55448286+taizan-hokuto@users.noreply.github.com' @@ -13,6 +13,8 @@ __all__ = ["core_async","core_multithread","processors"] from .api import ( LiveChat, LiveChatAsync, + ReplayChat, + ReplayChatAsync, ChatProcessor, CompatibleProcessor, SimpleDisplayProcessor, diff --git a/pytchat/api.py b/pytchat/api.py index 516a416..7fa873a 100644 --- a/pytchat/api.py +++ b/pytchat/api.py @@ -1,5 +1,7 @@ -from .core_async.livechat import LiveChatAsync from .core_multithread.livechat import LiveChat +from .core_async.livechat import LiveChatAsync +from .core_multithread.replaychat import ReplayChat +from .core_async.replaychat import ReplayChatAsync from .processors.chat_processor import ChatProcessor from .processors.default.processor import DefaultProcessor from .processors.compatible.processor import CompatibleProcessor diff --git a/pytchat/config/__init__.py b/pytchat/config/__init__.py index b17df93..463f03c 100644 --- a/pytchat/config/__init__.py +++ b/pytchat/config/__init__.py @@ -1,4 +1,4 @@ import logging -LOGGER_MODE = logging.ERROR +LOGGER_MODE = logging.DEBUG headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'} diff --git a/pytchat/core_async/livechat.py b/pytchat/core_async/livechat.py index 9388442..15c757c 100644 --- a/pytchat/core_async/livechat.py +++ b/pytchat/core_async/livechat.py @@ -10,12 +10,11 @@ import urllib.parse from aiohttp.client_exceptions import ClientConnectorError from concurrent.futures import CancelledError from .buffer import Buffer -from .parser import Parser +from ..parser.live import Parser from .. import config from .. import mylogger from ..exceptions import ChatParseException,IllegalFunctionCall from ..paramgen import liveparam - from ..processors.default.processor import DefaultProcessor logger = mylogger.get_logger(__name__,mode=config.LOGGER_MODE) @@ -81,7 +80,7 @@ class LiveChatAsync: self._exception_handler = exception_handler self._direct_mode = direct_mode self._is_alive = True - + self._parser = Parser() self._setup() if not LiveChatAsync._setup_finished: @@ -164,7 +163,7 @@ class LiveChatAsync: livechat_json = (await self._get_livechat_json(continuation, session, headers) ) - metadata, chatdata = Parser.parse( livechat_json ) + metadata, chatdata = self._parser.parse( livechat_json ) timeout = metadata['timeoutMs']/1000 chat_component = { "video_id" : self.video_id, diff --git a/pytchat/core_async/replaychat.py b/pytchat/core_async/replaychat.py new file mode 100644 index 0000000..e28abb7 --- /dev/null +++ b/pytchat/core_async/replaychat.py @@ -0,0 +1,307 @@ +import aiohttp, asyncio +import datetime +import json +import random +import signal +import time +import traceback +import urllib.parse +from aiohttp.client_exceptions import ClientConnectorError +from concurrent.futures import CancelledError +from queue import Queue +from .buffer import Buffer +from ..parser.replay import Parser +from .. import config +from .. import mylogger +from ..exceptions import ChatParseException,IllegalFunctionCall +from ..paramgen import arcparam +from ..processors.default.processor import DefaultProcessor + +logger = mylogger.get_logger(__name__,mode=config.LOGGER_MODE) +MAX_RETRY = 10 +headers = config.headers + +class ReplayChatAsync: + ''' aiohttpを利用してYouTubeのライブ配信のチャットデータを取得する + + Parameter + --------- + video_id : str + 動画ID + + processor : ChatProcessor + チャットデータを加工するオブジェクト + + buffer : Buffer(maxsize:20[default]) + チャットデータchat_componentを格納するバッファ。 + maxsize : 格納できるchat_componentの個数 + default値20個。1個で約5~10秒分。 + + interruptable : bool + Ctrl+Cによる処理中断を行うかどうか。 + + callback : func + _listen()関数から一定間隔で自動的に呼びだす関数。 + + done_callback : func + listener終了時に呼び出すコールバック。 + + direct_mode : bool + Trueの場合、bufferを使わずにcallbackを呼ぶ。 + Trueの場合、callbackの設定が必須 + (設定していない場合IllegalFunctionCall例外を発生させる) + + Attributes + --------- + _executor : ThreadPoolExecutor + チャットデータ取得ループ(_listen)用のスレッド + + _is_alive : bool + チャット取得を終了したか + ''' + + _setup_finished = False + + def __init__(self, video_id, + seektime =0, + processor = DefaultProcessor(), + buffer = Buffer(maxsize = 20), + interruptable = True, + callback = None, + done_callback = None, + exception_handler = None, + direct_mode = False): + self.video_id = video_id + self.seektime= seektime + self.processor = processor + self._buffer = buffer + self._callback = callback + self._done_callback = done_callback + self._exception_handler = exception_handler + self._direct_mode = direct_mode + self._is_alive = True + self._parser = Parser() + self._pauser = Queue() + self._pauser.put_nowait(None) + self._setup() + + if not ReplayChatAsync._setup_finished: + ReplayChatAsync._setup_finished = True + if exception_handler == None: + self._set_exception_handler(self._handle_exception) + else: + self._set_exception_handler(exception_handler) + if interruptable: + signal.signal(signal.SIGINT, + (lambda a, b:asyncio.create_task( + ReplayChatAsync.shutdown(None,signal.SIGINT,b)) + )) + + def _setup(self): + #direct modeがTrueでcallback未設定の場合例外発生。 + if self._direct_mode: + if self._callback is None: + raise IllegalFunctionCall( + "direct_mode=Trueの場合callbackの設定が必須です。") + else: + #direct modeがFalseでbufferが未設定ならばデフォルトのbufferを作成 + if self._buffer is None: + self._buffer = Buffer(maxsize = 20) + #callbackが指定されている場合はcallbackを呼ぶループタスクを作成 + if self._callback is None: + pass + else: + #callbackを呼ぶループタスクの開始 + loop = asyncio.get_event_loop() + loop.create_task(self._callback_loop(self._callback)) + #_listenループタスクの開始 + loop = asyncio.get_event_loop() + listen_task = loop.create_task(self._startlisten()) + #add_done_callbackの登録 + if self._done_callback is None: + listen_task.add_done_callback(self.finish) + else: + listen_task.add_done_callback(self._done_callback) + + async def _startlisten(self): + """最初のcontinuationパラメータを取得し、 + _listenループのタスクを作成し開始する + """ + initial_continuation = await self._get_initial_continuation() + if initial_continuation is None: + self.terminate() + logger.debug(f"[{self.video_id}]No initial continuation.") + return + await self._listen(initial_continuation) + + async def _get_initial_continuation(self): + ''' チャットデータ取得に必要な最初のcontinuationを取得する。''' + try: + initial_continuation = arcparam.get(self.video_id,self.seektime) + except ChatParseException as e: + self.terminate() + logger.debug(f"[{self.video_id}]Error:{str(e)}") + return + except KeyError: + logger.debug(f"[{self.video_id}]KeyError:" + f"{traceback.format_exc(limit = -1)}") + self.terminate() + return + return initial_continuation + + async def _listen(self, continuation): + ''' continuationに紐付いたチャットデータを取得し + にチャットデータを格納、 + 次のcontinuaitonを取得してループする + + Parameter + --------- + continuation : str + 次のチャットデータ取得に必要なパラメータ + ''' + try: + async with aiohttp.ClientSession() as session: + while(continuation and self._is_alive): + if self._pauser.empty(): + #pauseが呼ばれて_pauserが空状態のときは一時停止する + await self._pauser.get() + #resumeが呼ばれて_pauserにitemが入ったら再開する + #直後に_pauserにitem(None)を入れてブロックを防ぐ + self._pauser.put_nowait(None) + livechat_json = (await + self._get_livechat_json(continuation, session, headers) + ) + metadata, chatdata = self._parser.parse( livechat_json ) + timeout = metadata['timeoutMs']/1000 + chat_component = { + "video_id" : self.video_id, + "timeout" : timeout, + "chatdata" : chatdata + } + time_mark =time.time() + if self._direct_mode: + await self._callback( + self.processor.process([chat_component]) + ) + else: + await self._buffer.put(chat_component) + diff_time = timeout - (time.time()-time_mark) + if diff_time < 0 : diff_time=0 + await asyncio.sleep(diff_time) + continuation = metadata.get('continuation') + except ChatParseException as e: + logger.error(f"{str(e)}(動画ID:\"{self.video_id}\")") + return + except (TypeError , json.JSONDecodeError) : + logger.error(f"{traceback.format_exc(limit = -1)}") + return + + logger.debug(f"[{self.video_id}]チャット取得を終了しました。") + + async def _get_livechat_json(self, continuation, session, headers): + ''' + チャットデータが格納されたjsonデータを取得する。 + ''' + continuation = urllib.parse.quote(continuation) + livechat_json = None + status_code = 0 + url =( + f"https://www.youtube.com/live_chat_replay/get_live_chat_replay?" + f"continuation={continuation}&pbj=1") + for _ in range(MAX_RETRY + 1): + async with session.get(url ,headers = headers) as resp: + try: + text = await resp.text() + status_code = resp.status + livechat_json = json.loads(text) + break + except (ClientConnectorError,json.JSONDecodeError) : + await asyncio.sleep(1) + continue + else: + logger.error(f"[{self.video_id}]" + f"Exceeded retry count. status_code={status_code}") + return None + return livechat_json + + async def _callback_loop(self,callback): + """ コンストラクタでcallbackを指定している場合、バックグラウンドで + callbackに指定された関数に一定間隔でチャットデータを投げる。 + + Parameter + --------- + callback : func + 加工済みのチャットデータを渡す先の関数。 + """ + while self.is_alive(): + items = await self._buffer.get() + data = self.processor.process(items) + await callback(data) + + async def get(self): + """ bufferからデータを取り出し、processorに投げ、 + 加工済みのチャットデータを返す。 + + Returns + : Processorによって加工されたチャットデータ + """ + if self._callback is None: + items = await self._buffer.get() + return self.processor.process(items) + raise IllegalFunctionCall( + "既にcallbackを登録済みのため、get()は実行できません。") + + def pause(self): + if not self._pauser.empty(): + self._pauser.get() + + def resume(self): + if self._pauser.empty(): + self._pauser.put_nowait(None) + + + def is_alive(self): + return self._is_alive + + def finish(self,sender): + '''Listener終了時のコールバック''' + try: + self.terminate() + except CancelledError: + logger.debug(f'[{self.video_id}]cancelled:{sender}') + + def terminate(self): + ''' + Listenerを終了する。 + ''' + self._is_alive = False + if self._direct_mode == False: + #bufferにダミーオブジェクトを入れてis_alive()を判定させる + self._buffer.put_nowait({'chatdata':'','timeout':1}) + logger.info(f'終了しました:[{self.video_id}]') + + @classmethod + def _set_exception_handler(cls, handler): + loop = asyncio.get_event_loop() + #default handler: cls._handle_exception + loop.set_exception_handler(handler) + + @classmethod + def _handle_exception(cls, loop, context): + #msg = context.get("exception", context["message"]) + if not isinstance(context["exception"],CancelledError): + logger.error(f"Caught exception: {context}") + loop= asyncio.get_event_loop() + loop.create_task(cls.shutdown(None,None,None)) + + @classmethod + async def shutdown(cls, event, sig = None, handler=None): + logger.debug("シャットダウンしています") + tasks = [t for t in asyncio.all_tasks() if t is not + asyncio.current_task()] + [task.cancel() for task in tasks] + + logger.debug(f"残っているタスクを終了しています") + await asyncio.gather(*tasks,return_exceptions=True) + loop = asyncio.get_event_loop() + loop.stop() \ No newline at end of file diff --git a/pytchat/core_multithread/livechat.py b/pytchat/core_multithread/livechat.py index 0e4e076..c47cae8 100644 --- a/pytchat/core_multithread/livechat.py +++ b/pytchat/core_multithread/livechat.py @@ -3,13 +3,12 @@ import datetime import json import random import signal -import threading import time import traceback import urllib.parse from concurrent.futures import CancelledError, ThreadPoolExecutor from .buffer import Buffer -from .parser import Parser +from ..parser.live import Parser from .. import config from .. import mylogger from ..exceptions import ChatParseException,IllegalFunctionCall diff --git a/pytchat/core_multithread/replaychat.py b/pytchat/core_multithread/replaychat.py new file mode 100644 index 0000000..f8902b1 --- /dev/null +++ b/pytchat/core_multithread/replaychat.py @@ -0,0 +1,284 @@ +import requests +import datetime +import json +import random +import signal +import time +import traceback +import urllib.parse +from concurrent.futures import CancelledError, ThreadPoolExecutor +from queue import Queue +from .buffer import Buffer +from ..parser.replay import Parser +from .. import config +from .. import mylogger +from ..exceptions import ChatParseException,IllegalFunctionCall +from ..paramgen import arcparam +from ..processors.default.processor import DefaultProcessor + +logger = mylogger.get_logger(__name__,mode=config.LOGGER_MODE) +MAX_RETRY = 10 +headers = config.headers + + + +class ReplayChat: + ''' スレッドプールを利用してYouTubeのライブ配信のチャットデータを取得する + + Parameter + --------- + video_id : str + 動画ID + + processor : ChatProcessor + チャットデータを加工するオブジェクト + + buffer : Buffer(maxsize:20[default]) + チャットデータchat_componentを格納するバッファ。 + maxsize : 格納できるchat_componentの個数 + default値20個。1個で約5~10秒分。 + + interruptable : bool + Ctrl+Cによる処理中断を行うかどうか。 + + callback : func + _listen()関数から一定間隔で自動的に呼びだす関数。 + + done_callback : func + listener終了時に呼び出すコールバック。 + + direct_mode : bool + Trueの場合、bufferを使わずにcallbackを呼ぶ。 + Trueの場合、callbackの設定が必須 + (設定していない場合IllegalFunctionCall例外を発生させる) + + Attributes + --------- + _executor : ThreadPoolExecutor + チャットデータ取得ループ(_listen)用のスレッド + + _is_alive : bool + チャット取得を終了したか + ''' + + _setup_finished = False + #チャット監視中のListenerのリスト + _listeners= [] + def __init__(self, video_id, + seektime =0, + processor = DefaultProcessor(), + buffer = Buffer(maxsize = 20), + interruptable = True, + callback = None, + done_callback = None, + direct_mode = False + ): + self.video_id = video_id + self.seektime= seektime + self.processor = processor + self._buffer = buffer + self._callback = callback + self._done_callback = done_callback + self._executor = ThreadPoolExecutor(max_workers=2) + self._direct_mode = direct_mode + self._is_alive = True + self._parser = Parser() + self._pauser = Queue() + self._pauser.put_nowait(None) + + self._setup() + if not ReplayChat._setup_finished: + ReplayChat._setup_finished = True + if interruptable: + signal.signal(signal.SIGINT, (lambda a, b: + (ReplayChat.shutdown(None,signal.SIGINT,b)) + )) + ReplayChat._listeners.append(self) + + def _setup(self): + #direct modeがTrueでcallback未設定の場合例外発生。 + if self._direct_mode: + if self._callback is None: + raise IllegalFunctionCall( + "direct_mode=Trueの場合callbackの設定が必須です。") + else: + #direct modeがFalseでbufferが未設定ならばデフォルトのbufferを作成 + if self._buffer is None: + self._buffer = Buffer(maxsize = 20) + #callbackが指定されている場合はcallbackを呼ぶループタスクを作成 + if self._callback is None: + pass + else: + #callbackを呼ぶループタスクの開始 + self._executor.submit(self._callback_loop,self._callback) + #_listenループタスクの開始 + listen_task = self._executor.submit(self._startlisten) + #add_done_callbackの登録 + if self._done_callback is None: + listen_task.add_done_callback(self.finish) + else: + listen_task.add_done_callback(self._done_callback) + + def _startlisten(self): + """最初のcontinuationパラメータを取得し、 + _listenループのタスクを作成し開始する + """ + initial_continuation = self._get_initial_continuation() + if initial_continuation is None: + self.terminate() + logger.debug(f"[{self.video_id}]No initial continuation.") + return + self._listen(initial_continuation) + + def _get_initial_continuation(self): + ''' チャットデータ取得に必要な最初のcontinuationを取得する。''' + try: + initial_continuation = arcparam.get(self.video_id,self.seektime) + except ChatParseException as e: + self.terminate() + logger.debug(f"[{self.video_id}]Error:{str(e)}") + return + except KeyError: + logger.debug(f"[{self.video_id}]KeyError:" + f"{traceback.format_exc(limit = -1)}") + self.terminate() + return + return initial_continuation + + def _listen(self, continuation): + ''' continuationに紐付いたチャットデータを取得し + にチャットデータを格納、 + 次のcontinuaitonを取得してループする + + Parameter + --------- + continuation : str + 次のチャットデータ取得に必要なパラメータ + ''' + try: + with requests.Session() as session: + while(continuation and self._is_alive): + if self._pauser.empty(): + #pauseが呼ばれて_pauserが空状態のときは一時停止する + self._pauser.get() + #resumeが呼ばれて_pauserにitemが入ったら再開する + #直後に_pauserにitem(None)を入れてブロックを防ぐ + self._pauser.put_nowait(None) + livechat_json = ( + self._get_livechat_json(continuation, session, headers) + ) + metadata, chatdata = self._parser.parse( livechat_json ) + #チャットデータを含むコンポーネントを組み立ててbufferに投入する + timeout = metadata['timeoutMs']/1000 + chat_component = { + "video_id" : self.video_id, + "timeout" : timeout, + "chatdata" : chatdata + } + time_mark =time.time() + if self._direct_mode: + self._callback( + self.processor.process([chat_component]) + ) + else: + self._buffer.put(chat_component) + diff_time = timeout - (time.time()-time_mark) + if diff_time < 0 : diff_time=0 + time.sleep(diff_time) + continuation = metadata.get('continuation') + except ChatParseException as e: + logger.error(f"{str(e)}(動画ID:\"{self.video_id}\")") + return + except (TypeError , json.JSONDecodeError) : + logger.error(f"{traceback.format_exc(limit = -1)}") + return + + logger.debug(f"[{self.video_id}]チャット取得を終了しました。") + + def _get_livechat_json(self, continuation, session, headers): + ''' + チャットデータが格納されたjsonデータを取得する。 + ''' + continuation = urllib.parse.quote(continuation) + livechat_json = None + status_code = 0 + url =( + f"https://www.youtube.com/live_chat_replay/get_live_chat_replay?" + f"continuation={continuation}&pbj=1") + for _ in range(MAX_RETRY + 1): + with session.get(url ,headers = headers) as resp: + try: + text = resp.text + status_code = resp.status_code + livechat_json = json.loads(text) + break + except json.JSONDecodeError : + time.sleep(1) + continue + else: + logger.error(f"[{self.video_id}]" + f"Exceeded retry count. status_code={status_code}") + return None + return livechat_json + + def _callback_loop(self,callback): + """ コンストラクタでcallbackを指定している場合、バックグラウンドで + callbackに指定された関数に一定間隔でチャットデータを投げる。 + + Parameter + --------- + callback : func + 加工済みのチャットデータを渡す先の関数。 + """ + while self.is_alive(): + items = self._buffer.get() + data = self.processor.process(items) + callback(data) + + def get(self): + """ bufferからデータを取り出し、processorに投げ、 + 加工済みのチャットデータを返す。 + + Returns + : Processorによって加工されたチャットデータ + """ + if self._callback is None: + items = self._buffer.get() + return self.processor.process(items) + raise IllegalFunctionCall( + "既にcallbackを登録済みのため、get()は実行できません。") + + def pause(self): + if not self._pauser.empty(): + self._pauser.get() + + def resume(self): + if self._pauser.empty(): + self._pauser.put_nowait(None) + + + def is_alive(self): + return self._is_alive + + def finish(self,sender): + '''Listener終了時のコールバック''' + try: + self.terminate() + except CancelledError: + logger.debug(f'[{self.video_id}]cancelled:{sender}') + + def terminate(self): + ''' + Listenerを終了する。 + ''' + self._is_alive = False + if self._direct_mode == False: + #bufferにダミーオブジェクトを入れてis_alive()を判定させる + self._buffer.put({'chatdata':'','timeout':1}) + logger.info(f'終了しました:[{self.video_id}]') + + @classmethod + def shutdown(cls, event, sig = None, handler=None): + logger.debug("シャットダウンしています") + for t in ReplayChat._listeners: + t._is_alive = False \ No newline at end of file diff --git a/pytchat/paramgen/arcparam.py b/pytchat/paramgen/arcparam.py new file mode 100644 index 0000000..6cc7650 --- /dev/null +++ b/pytchat/paramgen/arcparam.py @@ -0,0 +1,120 @@ +from base64 import urlsafe_b64encode as b64enc +from functools import reduce +import calendar, datetime, pytz +import math +import random +import urllib.parse + +''' +Generate continuation parameter of youtube replay chat. + +Author: taizan-hokuto (2019) @taizan205 + +ver 0.0.1 2019.10.05 +''' + +def _gen_vid(video_id): + """generate video_id parameter. + Parameter + --------- + video_id : str + + Return + --------- + byte[] : base64 encoded video_id parameter. + """ + header_magic = b'\x0A\x0F\x1A\x0D\x0A' + header_id = video_id.encode() + header_sep_1 = b'\x1A\x13\xEA\xA8\xDD\xB9\x01\x0D\x0A\x0B' + header_terminator = b'\x20\x01' + + item = [ + header_magic, + _nval(len(header_id)), + header_id, + header_sep_1, + header_id, + header_terminator + ] + + return urllib.parse.quote( + b64enc(reduce(lambda x, y: x+y, item)).decode() + ).encode() + +def _nval(val): + """convert value to byte array""" + if val<0: raise ValueError + buf = b'' + while val >> 7: + m = val & 0xFF | 0x80 + buf += m.to_bytes(1,'big') + val >>= 7 + buf += val.to_bytes(1,'big') + return buf + + +def _tzparity(video_id,times): + t=0 + for i,s in enumerate(video_id): + ss = ord(s) + if(ss % 2 == 0): + t += ss*(12-i) + else: + t ^= ss*i + + return ((times^t) % 2).to_bytes(1,'big') + + +def get(video_id, seektime = 0, topchatonly = False): + switch_01 = b'\x04' if topchatonly else b'\x01' + + + if seektime < 0: + raise ValueError('seektime is 0 or positive number.') + if seektime == 0: + times =_nval(1) + switch = b'\x04' + else: + times =_nval(int(seektime*1000000)) + switch = b'\x03' + parity = _tzparity(video_id, seektime) + + header_magic= b'\xA2\x9D\xB0\xD3\x04' + sep_0 = b'\x1A' + vid = _gen_vid(video_id) + time_tag = b'\x28' + timestamp1 = times + sep_1 = b'\x30\x00\x38\x00\x40\x00\x48' + sep_2 = b'\x52\x1C\x08\x00\x10\x00\x18\x00\x20\x00' + chkstr = b'\x2A\x0E\x73\x74\x61\x74\x69\x63\x63\x68\x65\x63\x6B\x73\x75\x6D\x40' + sep_3 = b'\x00\x58\x03\x60' + sep_4 = b'\x68'+parity+b'\x72\x04\x08' + sep_5 = b'\x10'+parity+b'\x78\x00' + body = [ + sep_0, + _nval(len(vid)), + vid, + time_tag, + timestamp1, + sep_1, + switch, + sep_2, + chkstr, + sep_3, + switch_01, + sep_4, + switch_01, + sep_5 + ] + + body = reduce(lambda x, y: x+y, body) + + return urllib.parse.quote( + b64enc( header_magic + + _nval(len(body)) + + body + ).decode() + ) + + + diff --git a/pytchat/paramgen/liveparam.py b/pytchat/paramgen/liveparam.py index b289f2c..f53fdda 100644 --- a/pytchat/paramgen/liveparam.py +++ b/pytchat/paramgen/liveparam.py @@ -1,11 +1,16 @@ from base64 import urlsafe_b64encode as b64enc from functools import reduce import calendar, datetime, pytz -import math import random import urllib.parse +''' +Generate continuation parameter of youtube live chat. +Author: taizan-hokuto (2019) @taizan205 + +ver 0.0.1 2019.10.05 +''' def _gen_vid(video_id): """generate video_id parameter. Parameter @@ -39,6 +44,17 @@ def _gen_vid(video_id): b64enc(reduce(lambda x, y: x+y, item)).decode() ).encode() +def _tzparity(video_id,times): + t=0 + for i,s in enumerate(video_id): + ss = ord(s) + if(ss % 2 == 0): + t += ss*(12-i) + else: + t ^= ss*i + + return ((times^t) % 2).to_bytes(1,'big') + def _nval(val): """convert value to byte array""" if val<0: raise ValueError @@ -53,15 +69,16 @@ def _nval(val): def _build(video_id, _ts1, _ts2, _ts3, _ts4, _ts5, topchatonly = False): #_short_type2 switch_01 = b'\x04' if topchatonly else b'\x01' - header_magic= b'\xD2\x87\xCC\xC8\x03' + parity = _tzparity(video_id, _ts1^_ts2^_ts3^_ts4^_ts5) + header_magic= b'\xD2\x87\xCC\xC8\x03' sep_0 = b'\x1A' vid = _gen_vid(video_id) time_tag = b'\x28' timestamp1 = _nval(_ts1) sep_1 = b'\x30\x00\x38\x00\x40\x02\x4A' un_len = b'\x2B' - sep_2 = b'\x08\x00\x10\x00\x18\x00\x20\x00' + sep_2 = b'\x08'+parity+b'\x10\x00\x18\x00\x20\x00' chkstr = b'\x2A\x0E\x73\x74\x61\x74\x69\x63\x63\x68\x65\x63\x6B\x73\x75\x6D' sep_3 = b'\x3A\x00\x40\x00\x4A' sep_4_len = b'\x02' diff --git a/pytchat/parser/__init__.py b/pytchat/parser/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pytchat/core_multithread/parser.py b/pytchat/parser/live.py similarity index 100% rename from pytchat/core_multithread/parser.py rename to pytchat/parser/live.py diff --git a/pytchat/core_async/parser.py b/pytchat/parser/replay.py similarity index 60% rename from pytchat/core_async/parser.py rename to pytchat/parser/replay.py index 16a7412..bec801d 100644 --- a/pytchat/core_async/parser.py +++ b/pytchat/parser/replay.py @@ -11,8 +11,7 @@ logger = mylogger.get_logger(__name__,mode=config.LOGGER_MODE) class Parser: - @classmethod - def parse(cls, jsn): + def parse(self, jsn): if jsn is None: return {'timeoutMs':0,'continuation':None},[] if jsn['response']['responseContext'].get('errors'): @@ -26,15 +25,28 @@ class Parser: cont = contents['liveChatContinuation']['continuations'][0] if cont is None: raise NoContinuationsException('Continuationがありません。') - metadata = (cont.get('invalidationContinuationData') or - cont.get('timedContinuationData') or - cont.get('reloadContinuationData') - ) + metadata = cont.get('liveChatReplayContinuationData') if metadata is None: unknown = list(cont.keys())[0] if unknown: - logger.error(f"Received unknown continuation type:{unknown}") metadata = cont.get(unknown) - metadata.setdefault('timeoutMs', 10000) - chatdata = contents['liveChatContinuation'].get('actions') + + actions = contents['liveChatContinuation'].get('actions') + if actions is None: + raise NoContentsException('チャットデータを取得できませんでした。') + interval = self.get_interval(actions) + metadata.setdefault("timeoutMs",interval) + chatdata = [] + for action in actions: + chatdata.append(action["replayChatItemAction"]["actions"][0]) return metadata, chatdata + + def get_interval(self, actions: list): + if actions is None: + return 0 + start = int(actions[0]["replayChatItemAction"]["videoOffsetTimeMsec"]) + last = int(actions[-1]["replayChatItemAction"]["videoOffsetTimeMsec"]) + return (last - start) + + + diff --git a/pytchat/processors/default/processor.py b/pytchat/processors/default/processor.py index 7059901..7806a6d 100644 --- a/pytchat/processors/default/processor.py +++ b/pytchat/processors/default/processor.py @@ -13,13 +13,13 @@ class Chatdata: def tick(self): if self.interval == 0: - time.sleep(3) + time.sleep(1) return time.sleep(self.interval/len(self.items)) async def tick_async(self): if self.interval == 0: - await asyncio.sleep(0.5) + await asyncio.sleep(1) return await asyncio.sleep(self.interval/len(self.items)) diff --git a/pytchat/processors/default/renderer/base.py b/pytchat/processors/default/renderer/base.py index c555b70..507a949 100644 --- a/pytchat/processors/default/renderer/base.py +++ b/pytchat/processors/default/renderer/base.py @@ -13,6 +13,11 @@ class BaseRenderer: self.id = self.renderer.get('id') timestampUsec = int(self.renderer.get("timestampUsec",0)) self.timestamp = int(timestampUsec/1000) + tst = self.renderer.get("timestampText") + if tst: + self.timestampText = tst.get("simpleText") + else: + self.timestampText = "" self.datetime = self.get_datetime(timestampUsec) self.message = self.get_message(self.renderer) self.id = self.renderer.get('id') diff --git a/pytchat/util/__init__.py b/pytchat/util/__init__.py index 24b8e95..95ce56a 100644 --- a/pytchat/util/__init__.py +++ b/pytchat/util/__init__.py @@ -1,7 +1,7 @@ import requests,json,datetime from .. import config -def download(cls,url): +def download(url): _session = requests.Session() html = _session.get(url, headers=config.headers) with open(str(datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S') @@ -9,7 +9,7 @@ def download(cls,url): json.dump(html.json(),f,ensure_ascii=False) -def save(cls,data,filename): +def save(data,filename): with open(str(datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S') )+filename,mode ='w',encoding='utf-8') as f: f.writelines(data) diff --git a/tests/test_arcparam.py b/tests/test_arcparam.py new file mode 100644 index 0000000..926dd59 --- /dev/null +++ b/tests/test_arcparam.py @@ -0,0 +1,26 @@ +import pytest +from pytchat.parser.replay import Parser +import pytchat.config as config +import requests, json +from pytchat.paramgen import arcparam + +def test_arcparam_0(mocker): + param = arcparam.get("01234567890") + assert "op2w0wRyGjxDZzhhRFFvTE1ERXlNelExTmpjNE9UQWFFLXFvM2JrQkRRb0xNREV5TXpRMU5qYzRPVEFnQVElM0QlM0QoATAAOABAAEgEUhwIABAAGAAgACoOc3RhdGljY2hlY2tzdW1AAFgDYAFoAXIECAEQAXgA" == param + + +def test_arcparam_1(mocker): + param = arcparam.get("01234567890", seektime = 100000) + assert "op2w0wR3GjxDZzhhRFFvTE1ERXlNelExTmpjNE9UQWFFLXFvM2JrQkRRb0xNREV5TXpRMU5qYzRPVEFnQVElM0QlM0QogNDbw_QCMAA4AEAASANSHAgAEAAYACAAKg5zdGF0aWNjaGVja3N1bUAAWANgAWgBcgQIARABeAA%3D" == param + +def test_arcparam_2(mocker): + param = arcparam.get("SsjCnHOk-Sk") + url=f"https://www.youtube.com/live_chat_replay/get_live_chat_replay?continuation={param}&pbj=1" + resp = requests.Session().get(url,headers = config.headers) + jsn = json.loads(resp.text) + parser = Parser() + _ , chatdata = parser.parse(jsn) + test_id = chatdata[0]["addChatItemAction"]["item"]["liveChatTextMessageRenderer"]["id"] + print(test_id) + assert "CjoKGkNMYXBzZTdudHVVQ0Zjc0IxZ0FkTnFnQjVREhxDSnlBNHV2bnR1VUNGV0dnd2dvZDd3NE5aZy0w" == test_id + \ No newline at end of file diff --git a/tests/test_compatible_processor.py b/tests/test_compatible_processor.py index c4daa56..fc3051a 100644 --- a/tests/test_compatible_processor.py +++ b/tests/test_compatible_processor.py @@ -1,7 +1,7 @@ import json import pytest import asyncio,aiohttp -from pytchat.core_async.parser import Parser +from pytchat.parser.live import Parser from pytchat.processors.compatible.processor import CompatibleProcessor from pytchat.exceptions import ( NoLivechatRendererException,NoYtinitialdataException, @@ -12,13 +12,15 @@ from pytchat.processors.compatible.renderer.paidmessage import LiveChatPaidMessa from pytchat.processors.compatible.renderer.paidsticker import LiveChatPaidStickerRenderer from pytchat.processors.compatible.renderer.legacypaid import LiveChatLegacyPaidMessageRenderer +parser = Parser() + def test_textmessage(mocker): '''api互換processorのテスト:通常テキストメッセージ''' processor = CompatibleProcessor() _json = _open_file("tests/testdata/compatible/textmessage.json") - _, chatdata = Parser.parse(json.loads(_json)) + _, chatdata = parser.parse(json.loads(_json)) data = { "video_id" : "", "timeout" : 7, @@ -55,7 +57,7 @@ def test_newsponcer(mocker): _json = _open_file("tests/testdata/compatible/newSponsor.json") - _, chatdata = Parser.parse(json.loads(_json)) + _, chatdata = parser.parse(json.loads(_json)) data = { "video_id" : "", "timeout" : 7, @@ -91,7 +93,7 @@ def test_superchat(mocker): _json = _open_file("tests/testdata/compatible/superchat.json") - _, chatdata = Parser.parse(json.loads(_json)) + _, chatdata = parser.parse(json.loads(_json)) data = { "video_id" : "", "timeout" : 7, diff --git a/tests/test_livechat.py b/tests/test_livechat.py index daa69e0..475f26c 100644 --- a/tests/test_livechat.py +++ b/tests/test_livechat.py @@ -1,6 +1,6 @@ import pytest -from pytchat.core_async.parser import Parser as AsyncParser -from pytchat.core_multithread.parser import Parser as ThreadParser +from pytchat.parser.live import Parser + import json import asyncio,aiohttp diff --git a/tests/test_liveparam.py b/tests/test_liveparam.py new file mode 100644 index 0000000..320a15f --- /dev/null +++ b/tests/test_liveparam.py @@ -0,0 +1,9 @@ +import pytest +from pytchat.paramgen import liveparam + +def test_liveparam_0(mocker): + _ts1= 1546268400 + param = liveparam._build("01234567890", + *([_ts1*1000000 for i in range(5)])) + test_param="0ofMyAPiARp8Q2c4S0RRb0xNREV5TXpRMU5qYzRPVEFhUTZxNXdiMEJQUW83YUhSMGNITTZMeTkzZDNjdWVXOTFkSFZpWlM1amIyMHZiR2wyWlY5amFHRjBQM1k5TURFeU16UTFOamM0T1RBbWFYTmZjRzl3YjNWMFBURWdBZyUzRCUzRCiAuNbVqsrfAjAAOABAAkorCAEQABgAIAAqDnN0YXRpY2NoZWNrc3VtOgBAAEoCCAFQgLjW1arK3wJYA1CAuNbVqsrfAliAuNbVqsrfAmgBggEECAEQAIgBAKABgLjW1arK3wI%3D" + assert test_param == param \ No newline at end of file diff --git a/tests/test_parser.py b/tests/test_parser.py index 31ed8c3..b338908 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -1,5 +1,5 @@ import pytest -from pytchat.core_async.parser import Parser +from pytchat.parser.live import Parser import json import asyncio,aiohttp from aioresponses import aioresponses @@ -11,7 +11,7 @@ from pytchat.exceptions import ( def _open_file(path): with open(path,mode ='r',encoding = 'utf-8') as f: return f.read() - +parser = Parser() @aioresponses() def test_finishedlive(*mock): @@ -21,7 +21,7 @@ def test_finishedlive(*mock): _text = json.loads(_text) try: - Parser.parse(_text) + parser.parse(_text) assert False except NoContentsException: assert True @@ -34,7 +34,7 @@ def test_parsejson(*mock): _text = json.loads(_text) try: - Parser.parse(_text) + parser.parse(_text) jsn = _text timeout = jsn["response"]["continuationContents"]["liveChatContinuation"]["continuations"][0]["timedContinuationData"]["timeoutMs"] continuation = jsn["response"]["continuationContents"]["liveChatContinuation"]["continuations"][0]["timedContinuationData"]["continuation"] diff --git a/tests/testdata/chatreplay.json b/tests/testdata/chatreplay.json new file mode 100644 index 0000000..21a553f --- /dev/null +++ b/tests/testdata/chatreplay.json @@ -0,0 +1,3104 @@ +{ + "timing": { + "info": { + "st": 485 + } + }, + "endpoint": { + "commandMetadata": { + "webCommandMetadata": { + "url": "/live_chat_replay/get_live_chat_replay?continuation=op2w0wRyGjxDZzhhRFFvTFUzTnFRMjVJVDJzdFUyc2FFLXFvM2JrQkRRb0xVM05xUTI1SVQyc3RVMnNnQVElM0QlM0QoATAAOABAAEgEUhwIABAAGAAgACoOc3RhdGljY2hlY2tzdW1AAFgDYAFoAHIECAEQAHgA", + "rootVe": 83769 + } + }, + "urlEndpoint": { + "url": "/live_chat_replay/get_live_chat_replay?continuation=op2w0wRyGjxDZzhhRFFvTFUzTnFRMjVJVDJzdFUyc2FFLXFvM2JrQkRRb0xVM05xUTI1SVQyc3RVMnNnQVElM0QlM0QoATAAOABAAEgEUhwIABAAGAAgACoOc3RhdGljY2hlY2tzdW1AAFgDYAFoAHIECAEQAHgA" + } + }, + "response": { + "responseContext": { + "serviceTrackingParams": [ + { + "service": "CSI", + "params": [ + { + "key": "GetLiveChatReplay_rid", + "value": "0x914bb287d65159a8" + }, + { + "key": "c", + "value": "WEB" + }, + { + "key": "cver", + "value": "2.20191108.05.00" + }, + { + "key": "yt_li", + "value": "0" + } + ] + }, + { + "service": "GFEEDBACK", + "params": [ + { + "key": "e", + "value": "23744176,23748146,23768780,23788852,23804281,23836605,23837040,23837772,23837993,23839597,23840216,23842630,23842986,23845648,23846545,23848795,23856555,23858320,9449243,9471235" + }, + { + "key": "logged_in", + "value": "0" + } + ] + }, + { + "service": "GUIDED_HELP", + "params": [ + { + "key": "logged_in", + "value": "0" + } + ] + }, + { + "service": "ECATCHER", + "params": [ + { + "key": "client.name", + "value": "WEB" + }, + { + "key": "client.version", + "value": "2.20191108" + }, + { + "key": "innertube.build.changelist", + "value": "279110845" + }, + { + "key": "innertube.build.experiments.source_version", + "value": "279412129" + }, + { + "key": "innertube.build.label", + "value": "youtube.ytfe.innertube_20191107_5_RC0" + }, + { + "key": "innertube.build.timestamp", + "value": "1573150496" + }, + { + "key": "innertube.build.variants.checksum", + "value": "2f195780d2d4220c295f73ab388f3fd5" + }, + { + "key": "innertube.run.job", + "value": "ytfe-innertube-replica-only.ytfe" + } + ] + } + ], + "webResponseContextExtensionData": { + "ytConfigData": { + "csn": "CAXIXa-uHZnC4wL5nZ7oBQ", + "visitorData": "Cgsydml5dDBXN2VMayiIiqDuBQ%3D%3D" + } + } + }, + "continuationContents": { + "liveChatContinuation": { + "continuations": [ + { + "liveChatReplayContinuationData": { + "timeUntilLastMessageMsec": 5000, + "continuation": "op2w0wSKARpQQ2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUIo0cHd-g0wADgAQABIA1IcCAAQABgAIAAqDnN0YXRpY2NoZWNrc3VtQABYA2ABaAByBAgBEAB4AA%3D%3D" + } + }, + { + "playerSeekContinuationData": { + "continuation": "op2w0wSKARpQQ2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUIo0cHd-g0wADgAQABIBFIcCAAQABgAIAAqDnN0YXRpY2NoZWNrc3VtQABYA2ABaAByBAgBEAB4AA%3D%3D" + } + } + ], + "actions": [ + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "や" + } + ] + }, + "authorName": { + "simpleText": "だにょぉぉーん Frisk" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-7FouCu9_oqM/AAAAAAAAAAI/AAAAAAAAAAA/yvN3lB__FTk/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-7FouCu9_oqM/AAAAAAAAAAI/AAAAAAAAAAA/yvN3lB__FTk/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2p3S09nb2FRMHhoY0hObE4yNTBkVlZEUm1OelFqRm5RV1JPY1dkQ05WRVNIRU5LZVVFMGRYWnVkSFZWUTBaWFIyZDNaMjlrTjNjMFRscG5MVEFRQUJvNEdnMEtDMU56YWtOdVNFOXJMVk5yS2ljS0dGVkRTbWhxUlRkM1ltUlpRV0ZsTVVjeU5XMHdkRWhCUVJJTFUzTnFRMjVJVDJzdFUyc2dBU2dCTWhvS0dGVkRWMkZXTWtWVE9UbHRkMjFMVFRsWlNrUlpkM0pKUVElM0QlM0Q=" + } + }, + "id": "CjoKGkNMYXBzZTdudHVVQ0Zjc0IxZ0FkTnFnQjVREhxDSnlBNHV2bnR1VUNGV0dnd2dvZDd3NE5aZy0w", + "timestampUsec": "1571985910682806", + "authorExternalChannelId": "UCWaV2ES99mwmKM9YJDYwrIA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "1:41" + } + } + }, + "clientId": "CJyA4uvntuUCFWGgwgod7w4NZg-0" + } + } + ], + "videoOffsetTimeMsec": "101308" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "こんにちは" + } + ] + }, + "authorName": { + "simpleText": "ユロ" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-pGpp73yndNs/AAAAAAAAAAI/AAAAAAAAAAA/gLRYv3bUhlE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-pGpp73yndNs/AAAAAAAAAAI/AAAAAAAAAAA/gLRYv3bUhlE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMHR0TTJkMWNuQjBkVlZEUmxKVWFIZFJiMlExY0RSQ1pFRVNKME5PYW5sMGRVUndkSFZWUTBaa1JuUkxaMjlrTFVKelIybG5NVFUzTVRrNE5qUXpOams1TlJBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU16UkZkVVVIazBlSGxtYVhWNlRIVXRjbUo2WkZwMw==" + } + }, + "id": "CkUKGkNLbTNndXJwdHVVQ0ZSVGh3UW9kNXA0QmRBEidDTmp5dHVEcHR1VUNGZEZ0S2dvZC1Cc0dpZzE1NzE5ODY0MzY5OTU%3D", + "timestampUsec": "1571986438396841", + "authorExternalChannelId": "UC3DWTPy4xyfiuzLu-rbzdZw", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "10:29" + } + } + }, + "clientId": "CNjytuDptuUCFdFtKgod-BsGig1571986436995" + } + } + ], + "videoOffsetTimeMsec": "629420" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "шалом🕎" + } + ] + }, + "authorName": { + "simpleText": "Максим Пушкин" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-R6Xg7yZdebQ/AAAAAAAAAAI/AAAAAAAAAAA/uZSuW6TEu1c/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-R6Xg7yZdebQ/AAAAAAAAAAI/AAAAAAAAAAA/uZSuW6TEu1c/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDFNU1drdFRISjBkVlZEUmxKUVkzZFJiMlF5T1dORk9GRVNKME5LUkRNNU9YcHlkSFZWUTBaUlNrbHRkMjlrUjNCblFWZEJNVFUzTVRrNE5qazFPREl3T1JBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU5VWW5RM1VYUkNSVEJwTkZwdFlsaDFOa1pETFVWMw==" + } + }, + "id": "CkUKGkNNTElpLUxydHVVQ0ZSUGN3UW9kMjljRThREidDSkQzOTl6cnR1VUNGUUpJbXdvZEdwZ0FXQTE1NzE5ODY5NTgyMDk%3D", + "timestampUsec": "1571986958640194", + "authorExternalChannelId": "UCTbt7QtBE0i4ZmbXu6FC-Ew", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "19:09" + } + } + }, + "clientId": "CJD399zrtuUCFQJImwodGpgAWA1571986958209" + } + } + ], + "videoOffsetTimeMsec": "1149440" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "hi~" + } + ] + }, + "authorName": { + "simpleText": "[H i _ playlist ] _me" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-6sY04x8MH7g/AAAAAAAAAAI/AAAAAAAAAAA/ePmqYR26K-4/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-6sY04x8MH7g/AAAAAAAAAAI/AAAAAAAAAAA/ePmqYR26K-4/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMDFmVjJnNWRuTjBkVlZEUmxwTVluZFJiMlJTUmpoSFpGRVNHME5KUzFWeFkxOXpkSFZWUTBaVk9XVlpRVzlrWWtaWlVIQjNNQkFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTkRXVFZxU1hSSWNFSm9UVmRKYmpSQ1dHRlllV3hS" + } + }, + "id": "CjkKGkNNX1doOXZzdHVVQ0ZaTGJ3UW9kUkY4R2RREhtDSUtVcWNfc3R1VUNGVTllWUFvZGJGWVBwdzA%3D", + "timestampUsec": "1571987212331855", + "authorExternalChannelId": "UCCY5jItHpBhMWIn4BXaXylQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "23:23" + } + } + }, + "clientId": "CIKUqc_stuUCFU9eYAodbFYPpw0" + } + } + ], + "videoOffsetTimeMsec": "1403752" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "hi in Bangkok" + } + ] + }, + "authorName": { + "simpleText": "Bangrak House" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-9nyHyYIJyxA/AAAAAAAAAAI/AAAAAAAAAAA/vipyPpGCwSQ/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-9nyHyYIJyxA/AAAAAAAAAAI/AAAAAAAAAAA/vipyPpGCwSQ/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDlQWmpKd2VuVjBkVlZEUm1SaWFIZFJiMlJWV2tsR1VuY1NKME5PUnpaMWNFeDFkSFZWUTBaa1ZFaGpkMFZrWjJ4SlNrNTNNVFUzTVRrNE56WXhOemt4TWhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU00V1hsTVgxaHZSVkJSTXpKd2VqYzVkalJtWWkxbg==" + } + }, + "id": "CkUKGkNPT2YycHp1dHVVQ0ZkYmh3UW9kVVpJRlJ3EidDTkc2dXBMdXR1VUNGZFRIY3dFZGdsSUpOdzE1NzE5ODc2MTc5MTI%3D", + "timestampUsec": "1571987618435043", + "authorExternalChannelId": "UC8YyL_XoEPQ32pz79v4fb-g", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "30:08" + } + } + }, + "clientId": "CNG6upLutuUCFdTHcwEdglIJNw1571987617912" + } + } + ], + "videoOffsetTimeMsec": "1808926" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "Thank you" + } + ] + }, + "authorName": { + "simpleText": "melvin hamilton" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-6d3V4yG9txk/AAAAAAAAAAI/AAAAAAAAAAA/Tcfg_kI5qU4/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-6d3V4yG9txk/AAAAAAAAAAI/AAAAAAAAAAA/Tcfg_kI5qU4/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2p3S09nb2FRMHhUYkRFdFluZDBkVlZEUmxKWVluZFJiMlJKTFZsTFpsRVNIRU5KTTA0eVRqZDNkSFZWUTBaUk9HWkJkMjlrYTJKclRUSkJMVEFRQUJvNEdnMEtDMU56YWtOdVNFOXJMVk5yS2ljS0dGVkRTbWhxUlRkM1ltUlpRV0ZsTVVjeU5XMHdkRWhCUVJJTFUzTnFRMjVJVDJzdFUyc2dBU2dCTWhvS0dGVkRaRXRWWTFkTE5VdEJaMDV6VVVaYVJYRjFTVkpmVVElM0QlM0Q=" + } + }, + "id": "CjoKGkNMU2wxLWJ3dHVVQ0ZSWGJ3UW9kSS1ZS2ZREhxDSTNOMk43d3R1VUNGUThmQXdvZGtia00yQS0w", + "timestampUsec": "1571988310446772", + "authorExternalChannelId": "UCdKUcWK5KAgNsQFZEquIR_Q", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "41:41" + } + } + }, + "clientId": "CI3N2N7wtuUCFQ8fAwodkbkM2A-0" + } + } + ], + "videoOffsetTimeMsec": "2501844" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "🦋❤️👍" + } + ] + }, + "authorName": { + "simpleText": "σ ε" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-pDzS0FXknDY/AAAAAAAAAAI/AAAAAAAAAAA/LswHvFvF1V8/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-pDzS0FXknDY/AAAAAAAAAAI/AAAAAAAAAAA/LswHvFvF1V8/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMGw2ZWpJdGFuZDBkVlZEUmxsTU1YZFJiMlF3UTJOSVZtY1NKME5LWWtwbk9GQjNkSFZWUTBaWmNVZ3paMjlrZHkxQlEwTkJNVFUzTVRrNE9ETXhORFk1T0JBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU5QUTI1UlVqTnVZak5NY2tOTE5GbG9TblUyZERCMw==" + } + }, + "id": "CkUKGkNJenoyLWp3dHVVQ0ZZTDF3UW9kMENjSFZnEidDSmJKZzhQd3R1VUNGWXFIM2dvZHctQUNDQTE1NzE5ODgzMTQ2OTg%3D", + "timestampUsec": "1571988314716556", + "authorExternalChannelId": "UCOCnQR3nb3LrCK4YhJu6t0w", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "41:45" + } + } + }, + "clientId": "CJbJg8PwtuUCFYqH3godw-ACCA1571988314698" + } + } + ], + "videoOffsetTimeMsec": "2505715" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "안녕~" + } + ] + }, + "authorName": { + "simpleText": "이경민" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-9SOY3L3h55s/AAAAAAAAAAI/AAAAAAAAAAA/tTO-Mg44Tbs/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-9SOY3L3h55s/AAAAAAAAAAI/AAAAAAAAAAA/tTO-Mg44Tbs/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMGwyU205YU4zaDBkVlZEUm1NM2VYZFJiMlJyZWxWTGFVRVNHME5MZG1nNVNUZDRkSFZWUTBaU1VrRm9VVzlrYTNoTlIwWm5NQkFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTnVWakJpYUdGRGNGTlNWVkJQUnkxZmMzVnhlREZS" + } + }, + "id": "CjkKGkNJdkpvWjd4dHVVQ0ZjN3l3UW9ka3pVS2lBEhtDS3ZoOUk3eHR1VUNGUlJBaFFvZGt4TUdGZzA%3D", + "timestampUsec": "1571988427007115", + "authorExternalChannelId": "UCnV0bhaCpSRUPOG-_suqx1Q", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "43:38" + } + } + }, + "clientId": "CKvh9I7xtuUCFRRAhQodkxMGFg0" + } + } + ], + "videoOffsetTimeMsec": "2618354" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "こんにちは!" + } + ] + }, + "authorName": { + "simpleText": "まふまふ愛してる" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMUJVVUc1dk4zbDBkVlZEUmxJMFFURm5RV1IyYkRSTVZVRVNKME5RTTFKek5IcDVkSFZWUTBaalowMVhRVzlrUkdSUlJXaG5NVFUzTVRrNE9EWTJNVE14TVJBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU01TjBKaFJtOUVUekYxWTB0UE9YSkRUalJ2VVZaQg==" + } + }, + "id": "CkUKGkNQVFBubzd5dHVVQ0ZSNEExZ0Fkdmw0TFVBEidDUDNSczR6eXR1VUNGY2dNV0FvZERkUUVoZzE1NzE5ODg2NjEzMTE%3D", + "timestampUsec": "1571988661839860", + "authorExternalChannelId": "UC97BaFoDO1ucKO9rCN4oQVA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "47:33" + } + } + }, + "clientId": "CP3Rs4zytuUCFcgMWAodDdQEhg1571988661311" + } + } + ], + "videoOffsetTimeMsec": "2853340" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "woooow" + } + ] + }, + "authorName": { + "simpleText": "츄" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-SnlGRP-oThI/AAAAAAAAAAI/AAAAAAAAAAA/4AuU7O6i-58/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-SnlGRP-oThI/AAAAAAAAAAI/AAAAAAAAAAA/4AuU7O6i-58/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMHR4Tkd4MFZIbDBkVlZEUmxKUVRuZFJiMlJhZEd0S1ZVRVNKME5MY2xCNGMzSjVkSFZWUTBabGExaDBkMEZrZEZkWlIzcG5NVFUzTVRrNE9EZ3dPRGN3TUJBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU5hVG5kUlYzWjBXVWhXVkRKdmJrWldlbXBzTmkxUg==" + } + }, + "id": "CkUKGkNLcTRsdFR5dHVVQ0ZSUE53UW9kWnRrSlVBEidDS3JQeHNyeXR1VUNGZWtYdHdBZHRXWUd6ZzE1NzE5ODg4MDg3MDA%3D", + "timestampUsec": "1571988808506410", + "authorExternalChannelId": "UCZNwQWvtYHVT2onFVzjl6-Q", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "50:00" + } + } + }, + "clientId": "CKrPxsrytuUCFekXtwAdtWYGzg1571988808700" + } + } + ], + "videoOffsetTimeMsec": "3000275" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "音楽を聴いていると気持ちいい。" + } + ] + }, + "authorName": { + "simpleText": "まふまふ愛してる" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDh0WkhsMVdIbDBkVlZEUmxWMlNuZFJiMlJ2V0dOSmNuY1NKME5OZVVWdkxWUjVkSFZWUTBaWk1XUkxaMjlrWWpCSlQwZG5NVFUzTVRrNE9EZzBORFE0T1JBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU01TjBKaFJtOUVUekYxWTB0UE9YSkRUalJ2VVZaQg==" + } + }, + "id": "CkUKGkNPLWR5dVh5dHVVQ0ZVdkp3UW9kb1hjSXJ3EidDTXlFby1UeXR1VUNGWTFkS2dvZGIwSU9HZzE1NzE5ODg4NDQ0ODk%3D", + "timestampUsec": "1571988845006575", + "authorExternalChannelId": "UC97BaFoDO1ucKO9rCN4oQVA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "50:36" + } + } + }, + "clientId": "CMyEo-TytuUCFY1dKgodb0IOGg1571988844489" + } + } + ], + "videoOffsetTimeMsec": "3036293" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "아령" + } + ] + }, + "authorName": { + "simpleText": "Andy R" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-MttMuZY6RiI/AAAAAAAAAAI/AAAAAAAAAAA/uwveGKQip0I/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-MttMuZY6RiI/AAAAAAAAAAI/AAAAAAAAAAA/uwveGKQip0I/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2p3S09nb2FRMGszTVc5YWRucDBkVlZEUmxacWRYZFJiMlIyWlZGTkxXY1NIRU5QZG1WM1QycDVkSFZWUTBaU2RHcFpRVzlrVGtGTlFrWkJMVEFRQUJvNEdnMEtDMU56YWtOdVNFOXJMVk5yS2ljS0dGVkRTbWhxUlRkM1ltUlpRV0ZsTVVjeU5XMHdkRWhCUVJJTFUzTnFRMjVJVDJzdFUyc2dBU2dCTWhvS0dGVkRaR1F0WTAxMk9HZ3hSVXBDYjA1cFozQllWWEptVVElM0QlM0Q=" + } + }, + "id": "CjoKGkNJNzFvWnZ6dHVVQ0ZWanV3UW9kdmVRTS1nEhxDT3Zld09qeXR1VUNGUnRqWUFvZE5BTUJGQS0w", + "timestampUsec": "1571988957592206", + "authorExternalChannelId": "UCdd-cMv8h1EJBoNigpXUrfQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "52:28" + } + } + }, + "clientId": "COvewOjytuUCFRtjYAodNAMBFA-0" + } + } + ], + "videoOffsetTimeMsec": "3148639" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "나는 한국어를 배우고 있다" + } + ] + }, + "authorName": { + "simpleText": "まふまふ愛してる" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMHgyWjIwMldIcDBkVlZEUmxkNldYZFJiMlE0YmxGSGFGRVNKME5PV0ZNMVgxOTVkSFZWUTBaYVdXTlpRVzlrUVU1SlRYQm5NVFUzTVRrNE9EazNOemczTmhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU01TjBKaFJtOUVUekYxWTB0UE9YSkRUalJ2VVZaQg==" + } + }, + "id": "CkUKGkNMdmdtNlh6dHVVQ0ZXell3UW9kOG5RR2hREidDTlhTNV9feXR1VUNGWlljWUFvZEFOSU1wZzE1NzE5ODg5Nzc4NzY%3D", + "timestampUsec": "1571988978462779", + "authorExternalChannelId": "UC97BaFoDO1ucKO9rCN4oQVA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "52:49" + } + } + }, + "clientId": "CNXS5__ytuUCFZYcYAodANIMpg1571988977876" + } + } + ], + "videoOffsetTimeMsec": "3169427" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "今は4:37分だ" + } + ] + }, + "authorName": { + "simpleText": "まふまふ愛してる" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDlMZEd4TmFucDBkVlZEUm1SaWFIZFJiMlJyV0UxS1RYY1NKME5PZFc4MVkySjZkSFZWUTBaYVRWUlpRVzlrZGt0elRYSm5NVFUzTVRrNE9UQTFNVEU0TXhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU01TjBKaFJtOUVUekYxWTB0UE9YSkRUalJ2VVZaQg==" + } + }, + "id": "CkUKGkNPS3RsTWp6dHVVQ0ZkYmh3UW9ka1hNSk13EidDTnVvNWNienR1VUNGWk1UWUFvZHZLc01yZzE1NzE5ODkwNTExODM%3D", + "timestampUsec": "1571989051741922", + "authorExternalChannelId": "UC97BaFoDO1ucKO9rCN4oQVA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "54:02" + } + } + }, + "clientId": "CNuo5cbztuUCFZMTYAodvKsMrg1571989051183" + } + } + ], + "videoOffsetTimeMsec": "3242989" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatPaidMessageRenderer": { + "id": "ChwKGkNJZTl5ODN6dHVVQ0ZVcGRGUW9kT0ZjR01R", + "timestampUsec": "1571989077775669", + "authorName": { + "simpleText": "Svatopluk Čech" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-4PqtNbyI02Q/AAAAAAAAAAI/AAAAAAAAAAA/UCO9qZGm8t8/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-4PqtNbyI02Q/AAAAAAAAAAI/AAAAAAAAAAA/UCO9qZGm8t8/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "purchaseAmountText": { + "simpleText": "CZK 20.00" + }, + "message": { + "runs": [ + { + "text": "Hello from Czech Republic" + } + ] + }, + "headerBackgroundColor": 4278237396, + "headerTextColor": 4278190080, + "bodyBackgroundColor": 4278248959, + "bodyTextColor": 4278190080, + "authorExternalChannelId": "UCXpFDJR-iw7NQ_nbj3wx0cQ", + "authorNameTextColor": 3003121664, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2g0S0hBb2FRMGxsT1hrNE0zcDBkVlZEUmxWd1pFWlJiMlJQUm1OSFRWRVFBQm80R2cwS0MxTnpha051U0U5ckxWTnJLaWNLR0ZWRFNtaHFSVGQzWW1SWlFXRmxNVWN5Tlcwd2RFaEJRUklMVTNOcVEyNUlUMnN0VTJzZ0FTZ0JNaG9LR0ZWRFdIQkdSRXBTTFdsM04wNVJYMjVpYWpOM2VEQmpVUSUzRCUzRA==" + } + }, + "timestampColor": 2147483648, + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "54:29" + } + } + } + } + } + ], + "videoOffsetTimeMsec": "3269119" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "나두" + } + ] + }, + "authorName": { + "simpleText": "Andy R" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-MttMuZY6RiI/AAAAAAAAAAI/AAAAAAAAAAA/uwveGKQip0I/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-MttMuZY6RiI/AAAAAAAAAAI/AAAAAAAAAAA/uwveGKQip0I/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2p3S09nb2FRMGszYTJkMGJucDBkVlZEUmxKVlF6Rm5RV1JuY0d0RlYzY1NIRU5QZG1WM1QycDVkSFZWUTBaU2RHcFpRVzlrVGtGTlFrWkJMVEVRQUJvNEdnMEtDMU56YWtOdVNFOXJMVk5yS2ljS0dGVkRTbWhxUlRkM1ltUlpRV0ZsTVVjeU5XMHdkRWhCUVJJTFUzTnFRMjVJVDJzdFUyc2dBU2dCTWhvS0dGVkRaR1F0WTAxMk9HZ3hSVXBDYjA1cFozQllWWEptVVElM0QlM0Q=" + } + }, + "id": "CjoKGkNJN2tndG56dHVVQ0ZSVUMxZ0FkZ3BrRVd3EhxDT3Zld09qeXR1VUNGUnRqWUFvZE5BTUJGQS0x", + "timestampUsec": "1571989087105550", + "authorExternalChannelId": "UCdd-cMv8h1EJBoNigpXUrfQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "54:38" + } + } + }, + "clientId": "COvewOjytuUCFRtjYAodNAMBFA-1" + } + } + ], + "videoOffsetTimeMsec": "3278021" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "😍" + } + ] + }, + "authorName": { + "simpleText": "Yennie Srihandayanie" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-3iFq975mVjw/AAAAAAAAAAI/AAAAAAAAAAA/YOibd2zD1QU/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-3iFq975mVjw/AAAAAAAAAAI/AAAAAAAAAAA/YOibd2zD1QU/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMUJ0YnpoUGFucDBkVlZEUm1SRWQzZFJiMlJ1YUZsUVdVRVNHME5MVjNocFRXcDVkSFZWUTBabFRGWmpkMFZrVG1KM1N6bDNNQkFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTnhhbEk1YlVkU1IwNXRRMUZsWjNwNlMwZFVPR2wz" + } + }, + "id": "CjkKGkNQbW84T2p6dHVVQ0ZkRHd3UW9kbmhZUFlBEhtDS1d4aU1qeXR1VUNGZUxWY3dFZE5id0s5dzA%3D", + "timestampUsec": "1571989120357497", + "authorExternalChannelId": "UCqjR9mGRGNmCQegzzKGT8iw", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "55:11" + } + } + }, + "clientId": "CKWxiMjytuUCFeLVcwEdNbwK9w0" + } + } + ], + "videoOffsetTimeMsec": "3311340" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "영어는 어렵다" + } + ] + }, + "authorName": { + "simpleText": "まふまふ愛してる" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMHhVV25NdE4zcDBkVlZEUmxsNWIzZFJiMlIxWjFWQ2FWRVNKME5KTm5odVQySjZkSFZWUTBaV1NXaExaMjlrVDBoelFtUlJNVFUzTVRrNE9URXpNVE13TXhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU01TjBKaFJtOUVUekYxWTB0UE9YSkRUalJ2VVZaQg==" + } + }, + "id": "CkUKGkNMVFpzLTd6dHVVQ0ZZeW93UW9kdWdVQmlREidDSTZ4bk9ienR1VUNGVkloS2dvZE9Ic0JkUTE1NzE5ODkxMzEzMDM%3D", + "timestampUsec": "1571989131947188", + "authorExternalChannelId": "UC97BaFoDO1ucKO9rCN4oQVA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "55:22" + } + } + }, + "clientId": "CI6xnObztuUCFVIhKgodOHsBdQ1571989131303" + } + } + ], + "videoOffsetTimeMsec": "3322922" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "Music" + } + ] + }, + "authorName": { + "simpleText": "まふまふ愛してる" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDF0TW5aZmNucDBkVlZEUmxGaGFuZFJiMlJLWkZGRWVuY1NKME5NYVdWcVVHNTZkSFZWUTBaVk5VSm9VVzlrYlZaVlJHZG5NVFUzTVRrNE9URTFOamMwTWhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU01TjBKaFJtOUVUekYxWTB0UE9YSkRUalJ2VVZaQg==" + } + }, + "id": "CkUKGkNNbTJ2X3J6dHVVQ0ZRYWp3UW9kSmRRRHp3EidDTGllalBuenR1VUNGVTVCaFFvZG1WVURnZzE1NzE5ODkxNTY3NDI%3D", + "timestampUsec": "1571989157305161", + "authorExternalChannelId": "UC97BaFoDO1ucKO9rCN4oQVA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "55:48" + } + } + }, + "clientId": "CLiejPnztuUCFU5BhQodmVUDgg1571989156742" + } + } + ], + "videoOffsetTimeMsec": "3348698" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "한국어 잘하세요" + } + ] + }, + "authorName": { + "simpleText": "이희진" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-GiJkDQPu6rk/AAAAAAAAAAI/AAAAAAAAAAA/DAl3sxmc4nc/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-GiJkDQPu6rk/AAAAAAAAAAI/AAAAAAAAAAA/DAl3sxmc4nc/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDFsTW01UWRucDBkVlZEUm1GbVZYZFJiMlJJZFRCR1pVRVNKME5KWmxaMFQySjZkSFZWUTBaU2NGSlhRVzlrZEV0M1EzWm5NVFUzTVRrNE9URTFPREl5TWhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU0zUkdKS1NtaDBkME5pVUZkcGJIQnpTbll0UWpWbg==" + } + }, + "id": "CkUKGkNNZTJuUHZ6dHVVQ0ZhZlV3UW9kSHUwRmVBEidDSWZWdE9ienR1VUNGUnBSV0FvZHRLd0N2ZzE1NzE5ODkxNTgyMjI%3D", + "timestampUsec": "1571989158828871", + "authorExternalChannelId": "UC7DbJJhtwCbPWilpsJv-B5g", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "55:50" + } + } + }, + "clientId": "CIfVtObztuUCFRpRWAodtKwCvg1571989158222" + } + } + ], + "videoOffsetTimeMsec": "3350222" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "おつかれさま〜" + }, + { + "text": "😊😊😊" + } + ] + }, + "authorName": { + "simpleText": "Smile Smile" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-DbF250QeHlA/AAAAAAAAAAI/AAAAAAAAAAA/BLgx_hVN3yw/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-DbF250QeHlA/AAAAAAAAAAI/AAAAAAAAAAA/BLgx_hVN3yw/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2p3S09nb2FRMHBIY25kWlNEQjBkVlZEUmxGWVVuZFJiMlE0VUc5RFoxRVNIRU5PVjJWdkxWOTZkSFZWUTBaVk1IRkxaMjlrVVRCTlRrTjNMVEFRQUJvNEdnMEtDMU56YWtOdVNFOXJMVk5yS2ljS0dGVkRTbWhxUlRkM1ltUlpRV0ZsTVVjeU5XMHdkRWhCUVJJTFUzTnFRMjVJVDJzdFUyc2dBU2dCTWhvS0dGVkRWVlJYTm5oYVEwNURiakoyYzNaWlRHdzJaVlY1VVElM0QlM0Q=" + } + }, + "id": "CjoKGkNKR3J3WUgwdHVVQ0ZRWFJ3UW9kOFBvQ2dREhxDTldlby1fenR1VUNGVTBxS2dvZFEwTU5Ddy0w", + "timestampUsec": "1571989172016529", + "authorExternalChannelId": "UCUTW6xZCNCn2vsvYLl6eUyQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "56:03" + } + } + }, + "clientId": "CNWeo-_ztuUCFU0qKgodQ0MNCw-0" + } + } + ], + "videoOffsetTimeMsec": "3363790" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "한국어 연습" + } + ] + }, + "authorName": { + "simpleText": "まふまふ愛してる" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDVpY0RWSmJqQjBkVlZEUm1GVWVuZFJiMlJMYm1OSVpGRVNKME5NYVdWcVVHNTZkSFZWUTBaVk5VSm9VVzlrYlZaVlJHZG5NVFUzTVRrNE9URTRPRGM1TmhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU01TjBKaFJtOUVUekYxWTB0UE9YSkRUalJ2VVZaQg==" + } + }, + "id": "CkUKGkNOYnA1SW4wdHVVQ0ZhVHp3UW9kS25jSGRREidDTGllalBuenR1VUNGVTVCaFFvZG1WVURnZzE1NzE5ODkxODg3OTY%3D", + "timestampUsec": "1571989189375190", + "authorExternalChannelId": "UC97BaFoDO1ucKO9rCN4oQVA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "56:20" + } + } + }, + "clientId": "CLiejPnztuUCFU5BhQodmVUDgg1571989188796" + } + } + ], + "videoOffsetTimeMsec": "3380905" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "Hello from Armenia" + } + ] + }, + "authorName": { + "simpleText": "J Geo" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-UVjQg88jmQ8/AAAAAAAAAAI/AAAAAAAAAAA/7t5nT7P8vag/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-UVjQg88jmQ8/AAAAAAAAAAI/AAAAAAAAAAA/7t5nT7P8vag/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMDlMWTJrMGVqQjBkVlZEUm1GMlIzZFJiMlJ5ZURST1FVRVNHME5MZG1adE5HWXdkSFZWUTBaWmNVTXpaMjlrVWpCM1FqQkJNQkFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTnVkVXRpV0V0dVpGODFNa1pXTVdwMVUxWlhWRGgz" + } + }, + "id": "CjkKGkNPS2NpNHowdHVVQ0Zhdkd3UW9kcng0TkFBEhtDS3ZmbTRmMHR1VUNGWXFDM2dvZFIwd0IwQTA%3D", + "timestampUsec": "1571989194198626", + "authorExternalChannelId": "UCnuKbXKnd_52FV1juSVWT8w", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "56:25" + } + } + }, + "clientId": "CKvfm4f0tuUCFYqC3godR0wB0A0" + } + } + ], + "videoOffsetTimeMsec": "3385750" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "hiii" + } + ] + }, + "authorName": { + "simpleText": "فتاة الاوتاكو كيوكا كيو" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-VruOKNSwy7o/AAAAAAAAAAI/AAAAAAAAAAA/EM5kvPC-QZQ/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-VruOKNSwy7o/AAAAAAAAAAI/AAAAAAAAAAA/EM5kvPC-QZQ/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMHRtZG5ad2JqQjBkVlZEUmxWMlZuZFJiMlF5TkVWUE5tY1NKME5LWWpkclNsUXdkSFZWUTBaVlZFdFZVVzlrYm14QlNVNUJNVFUzTVRrNE9USXlNRGsyTnhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU5zUmpGWWRGSjRaMVZMY0Rsd1pXTm1XVzlGYVRkUg==" + } + }, + "id": "CkUKGkNLZnZ2cG4wdHVVQ0ZVdlZ3UW9kMjRFTzZnEidDSmI3a0pUMHR1VUNGVVRLVVFvZG5sQUlOQTE1NzE5ODkyMjA5Njc%3D", + "timestampUsec": "1571989222307751", + "authorExternalChannelId": "UClF1XtRxgUKp9pecfYoEi7Q", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "56:53" + } + } + }, + "clientId": "CJb7kJT0tuUCFUTKUQodnlAINA1571989220967" + } + } + ], + "videoOffsetTimeMsec": "3413529" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "ありがとうございます。" + } + ] + }, + "authorName": { + "simpleText": "まふまふ愛してる" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMHgxVkhwd2JqQjBkVlZEUmxGeGQzZFJiMlJUVGpoQmNYY1NKME5OVDFaMVNtb3dkSFZWUTBaUlZrZFhRVzlrTkhNMFRGTlJNVFUzTVRrNE9USXlNVGsyTVJBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU01TjBKaFJtOUVUekYxWTB0UE9YSkRUalJ2VVZaQg==" + } + }, + "id": "CkUKGkNMdVR6cG4wdHVVQ0ZRcXd3UW9kU044QXF3EidDTU9WdUpqMHR1VUNGUVZHV0FvZDRzNExTUTE1NzE5ODkyMjE5NjE%3D", + "timestampUsec": "1571989222558139", + "authorExternalChannelId": "UC97BaFoDO1ucKO9rCN4oQVA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "56:53" + } + } + }, + "clientId": "CMOVuJj0tuUCFQVGWAod4s4LSQ1571989221961" + } + } + ], + "videoOffsetTimeMsec": "3413779" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "from korea" + } + ] + }, + "authorName": { + "simpleText": "이희진" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-GiJkDQPu6rk/AAAAAAAAAAI/AAAAAAAAAAA/DAl3sxmc4nc/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-GiJkDQPu6rk/AAAAAAAAAAI/AAAAAAAAAAA/DAl3sxmc4nc/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMHh0V1c1eFREQjBkVlZEUmxWMlZuZFJiMlJXWW05TGRXY1NKME5KWmxaMFQySjZkSFZWUTBaU2NGSlhRVzlrZEV0M1EzWm5NVFUzTVRrNE9USTBNREE0TUJBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU0zUkdKS1NtaDBkME5pVUZkcGJIQnpTbll0UWpWbg==" + } + }, + "id": "CkUKGkNMbVlucUwwdHVVQ0ZVdlZ3UW9kVmJvS3VnEidDSWZWdE9ienR1VUNGUnBSV0FvZHRLd0N2ZzE1NzE5ODkyNDAwODA%3D", + "timestampUsec": "1571989240646713", + "authorExternalChannelId": "UC7DbJJhtwCbPWilpsJv-B5g", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "57:12" + } + } + }, + "clientId": "CIfVtObztuUCFRpRWAodtKwCvg1571989240080" + } + } + ], + "videoOffsetTimeMsec": "3432051" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "雨スゴい〜" + }, + { + "text": "😨💦💦" + } + ] + }, + "authorName": { + "simpleText": "Smile Smile" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-DbF250QeHlA/AAAAAAAAAAI/AAAAAAAAAAA/BLgx_hVN3yw/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-DbF250QeHlA/AAAAAAAAAAI/AAAAAAAAAAA/BLgx_hVN3yw/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2p3S09nb2FRMDVYVTIxTFZEQjBkVlZEUmxKTVkzZFJiMlJCY0hkUWFsRVNIRU5PVjJWdkxWOTZkSFZWUTBaVk1IRkxaMjlrVVRCTlRrTjNMVEVRQUJvNEdnMEtDMU56YWtOdVNFOXJMVk5yS2ljS0dGVkRTbWhxUlRkM1ltUlpRV0ZsTVVjeU5XMHdkRWhCUVJJTFUzTnFRMjVJVDJzdFUyc2dBU2dCTWhvS0dGVkRWVlJYTm5oYVEwNURiakoyYzNaWlRHdzJaVlY1VVElM0QlM0Q=" + } + }, + "id": "CjoKGkNOV1NtS1QwdHVVQ0ZSTGN3UW9kQXB3UGpREhxDTldlby1fenR1VUNGVTBxS2dvZFEwTU5Ddy0x", + "timestampUsec": "1571989244741973", + "authorExternalChannelId": "UCUTW6xZCNCn2vsvYLl6eUyQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "57:16" + } + } + }, + "clientId": "CNWeo-_ztuUCFU0qKgodQ0MNCw-1" + } + } + ], + "videoOffsetTimeMsec": "3436068" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "Hi from indonesia 🙌😊" + } + ] + }, + "authorName": { + "simpleText": "Waliyuddin sisila" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-TIoQvksTQlY/AAAAAAAAAAI/AAAAAAAAAAA/eOcRRQ--lZs/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-TIoQvksTQlY/AAAAAAAAAAI/AAAAAAAAAAA/eOcRRQ--lZs/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDVmYmw4MlpqQjBkVlZEUm1OTVVYZFJiMlJNUjI5SVNYY1NKME5RYlc5dlNYb3dkSFZWUTBaUmEwRXhVVzlrUTJWelRsUlJNVFUzTVRrNE9USTFNakExTmhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU0xUlhKUGFsZEhRMk5oVWxoNGJraE9jRVZVVWtKbg==" + } + }, + "id": "CkUKGkNOX25fNmYwdHVVQ0ZjTFF3UW9kTEdvSEl3EidDUG1vb0l6MHR1VUNGUWtBMVFvZENlc05UUTE1NzE5ODkyNTIwNTY%3D", + "timestampUsec": "1571989252731871", + "authorExternalChannelId": "UC5ErOjWGCcaRXxnHNpETRBg", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "57:23" + } + } + }, + "clientId": "CPmooIz0tuUCFQkA1QodCesNTQ1571989252056" + } + } + ], + "videoOffsetTimeMsec": "3443547" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "bye💔😖😭" + } + ] + }, + "authorName": { + "simpleText": "فتاة الاوتاكو كيوكا كيو" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-VruOKNSwy7o/AAAAAAAAAAI/AAAAAAAAAAA/EM5kvPC-QZQ/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-VruOKNSwy7o/AAAAAAAAAAI/AAAAAAAAAAA/EM5kvPC-QZQ/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMGxxYmkxeVdEQjBkVlZEUmxWdWNuZFJiMlJPYUZGTGJGRVNKME5LWWpkclNsUXdkSFZWUTBaVlZFdFZVVzlrYm14QlNVNUJNVFUzTVRrNE9USTRNRE0yTWhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU5zUmpGWWRGSjRaMVZMY0Rsd1pXTm1XVzlGYVRkUg==" + } + }, + "id": "CkUKGkNJam4tclgwdHVVQ0ZVbnJ3UW9kTmhRS2xREidDSmI3a0pUMHR1VUNGVVRLVVFvZG5sQUlOQTE1NzE5ODkyODAzNjI%3D", + "timestampUsec": "1571989282009992", + "authorExternalChannelId": "UClF1XtRxgUKp9pecfYoEi7Q", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "57:53" + } + } + }, + "clientId": "CJb7kJT0tuUCFUTKUQodnlAINA1571989280362" + } + } + ], + "videoOffsetTimeMsec": "3473764" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "ciao mondo.... 👋👋😁" + } + ] + }, + "authorName": { + "simpleText": "da re" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-YgZDF6KKE4c/AAAAAAAAAAI/AAAAAAAAAAA/yeahlcY42pc/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-YgZDF6KKE4c/AAAAAAAAAAI/AAAAAAAAAAA/yeahlcY42pc/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMUJYU0RCTVlqQjBkVlZEUm1OUVJYZFJiMlJJWWtWT1NIY1NKME5KWVhBNE5YWXdkSFZWUTBaalprd3hVVzlrVG1KUlJIbEJNVFUzTVRrNE9USTROREkzTnhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU5EV2kxaFpFVXdVMFJZWDBwSmJDMVlTMHhxUW05bg==" + } + }, + "id": "CkUKGkNQV0gwTGIwdHVVQ0ZjUEV3UW9kSGJFTkh3EidDSWFwODV2MHR1VUNGY2ZMMVFvZE5iUUR5QTE1NzE5ODkyODQyNzc%3D", + "timestampUsec": "1571989283406837", + "authorExternalChannelId": "UCCZ-adE0SDX_JIl-XKLjBog", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "57:55" + } + } + }, + "clientId": "CIap85v0tuUCFcfL1QodNbQDyA1571989284277" + } + } + ], + "videoOffsetTimeMsec": "3475221" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "雨が降る" + } + ] + }, + "authorName": { + "simpleText": "まふまふ愛してる" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDF4VTNCaVh6QjBkVlZEUmxKbWRIZFJiMlJmVm10TlQxRVNKME5MZGxjelltSXdkSFZWUTBaWlowNVpRVzlrUkdkclJtOUJNVFUzTVRrNE9UTXdNRGs0T1JBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU01TjBKaFJtOUVUekYxWTB0UE9YSkRUalJ2VVZaQg==" + } + }, + "id": "CkUKGkNNcVNwYl8wdHVVQ0ZSZnR3UW9kX1ZrTU9REidDS3ZXM2JiMHR1VUNGWWdOWUFvZERna0ZvQTE1NzE5ODkzMDA5ODk%3D", + "timestampUsec": "1571989301578058", + "authorExternalChannelId": "UC97BaFoDO1ucKO9rCN4oQVA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "58:12" + } + } + }, + "clientId": "CKvW3bb0tuUCFYgNYAodDgkFoA1571989300989" + } + } + ], + "videoOffsetTimeMsec": "3492968" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "bye koko san 😢😭" + } + ] + }, + "authorName": { + "simpleText": "Waliyuddin sisila" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-TIoQvksTQlY/AAAAAAAAAAI/AAAAAAAAAAA/eOcRRQ--lZs/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-TIoQvksTQlY/AAAAAAAAAAI/AAAAAAAAAAA/eOcRRQ--lZs/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDVNUld3NFREQjBkVlZEUmxsVGNYZFJiMlJEWldkS00xRVNKME5RYlc5dlNYb3dkSFZWUTBaUmEwRXhVVzlrUTJWelRsUlJNVFUzTVRrNE9UTXdOVEkzTmhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU0xUlhKUGFsZEhRMk5oVWxoNGJraE9jRVZVVWtKbg==" + } + }, + "id": "CkUKGkNOTEVsOEwwdHVVQ0ZZU3F3UW9kQ2VnSjNREidDUG1vb0l6MHR1VUNGUWtBMVFvZENlc05UUTE1NzE5ODkzMDUyNzY%3D", + "timestampUsec": "1571989307646546", + "authorExternalChannelId": "UC5ErOjWGCcaRXxnHNpETRBg", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "58:18" + } + } + }, + "clientId": "CPmooIz0tuUCFQkA1QodCesNTQ1571989305276" + } + } + ], + "videoOffsetTimeMsec": "3498945" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "da gusto" + } + ] + }, + "authorName": { + "simpleText": "Khastro J" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-vZNn-PLHKNw/AAAAAAAAAAI/AAAAAAAAAAA/rslpoFfthoA/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-vZNn-PLHKNw/AAAAAAAAAAI/AAAAAAAAAAA/rslpoFfthoA/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMHBpYzNFNE56QjBkVlZEUmxGaFUzZFJiMlJLVGpCUFdIY1NHME5LVUdNNVgzWjZkSFZWUTBaU2FXUkdVVzlrZVZWSlJrZDNNQkFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTlhRVXM0UjJkclExUm5UVXhyUzFsSFJtVllRMDlS" + } + }, + "id": "CjkKGkNKYnNxODcwdHVVQ0ZRYVN3UW9kSk4wT1h3EhtDSlBjOV92enR1VUNGUmlkRlFvZHlVSUZHdzA%3D", + "timestampUsec": "1571989333145110", + "authorExternalChannelId": "UCWAK8GgkCTgMLkKYGFeXCOQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "58:44" + } + } + }, + "clientId": "CJPc9_vztuUCFRidFQodyUIFGw0" + } + } + ], + "videoOffsetTimeMsec": "3524495" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "Hello" + }, + { + "text": "〜" + }, + { + "text": "(^" + }, + { + "text": "。" + }, + { + "text": "^)" + } + ] + }, + "authorName": { + "simpleText": "Smile Smile" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-DbF250QeHlA/AAAAAAAAAAI/AAAAAAAAAAA/BLgx_hVN3yw/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-DbF250QeHlA/AAAAAAAAAAI/AAAAAAAAAAA/BLgx_hVN3yw/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2p3S09nb2FRMHRQZW5wME56QjBkVlZEUmxweGIzZFJiMlJ1UkZWR1NrRVNIRU5PVjJWdkxWOTZkSFZWUTBaVk1IRkxaMjlrVVRCTlRrTjNMVE1RQUJvNEdnMEtDMU56YWtOdVNFOXJMVk5yS2ljS0dGVkRTbWhxUlRkM1ltUlpRV0ZsTVVjeU5XMHdkRWhCUVJJTFUzTnFRMjVJVDJzdFUyc2dBU2dCTWhvS0dGVkRWVlJYTm5oYVEwNURiakoyYzNaWlRHdzJaVlY1VVElM0QlM0Q=" + } + }, + "id": "CjoKGkNLT3p6dDcwdHVVQ0ZacW93UW9kbkRVRkpBEhxDTldlby1fenR1VUNGVTBxS2dvZFEwTU5Ddy0z", + "timestampUsec": "1571989367265699", + "authorExternalChannelId": "UCUTW6xZCNCn2vsvYLl6eUyQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "59:18" + } + } + }, + "clientId": "CNWeo-_ztuUCFU0qKgodQ0MNCw-3" + } + } + ], + "videoOffsetTimeMsec": "3558710" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "私は東京にいる。" + } + ] + }, + "authorName": { + "simpleText": "まふまふ愛してる" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMUJFUXpST1h6QjBkVlZEUmxObVZuZFJiMlJmY0ZWQ2EzY1NKME5NYWw5M09UY3dkSFZWUTBaUk5HOUxaMjlrZFRBMFJIWkJNVFUzTVRrNE9UTTJPVEE0TUJBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU01TjBKaFJtOUVUekYxWTB0UE9YSkRUalJ2VVZaQg==" + } + }, + "id": "CkUKGkNQREM0Tl8wdHVVQ0ZTZlZ3UW9kX3BVQmt3EidDTGpfdzk3MHR1VUNGUTRvS2dvZHUwNER2QTE1NzE5ODkzNjkwODA%3D", + "timestampUsec": "1571989369659760", + "authorExternalChannelId": "UC97BaFoDO1ucKO9rCN4oQVA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "59:20" + } + } + }, + "clientId": "CLj_w970tuUCFQ4oKgodu04DvA1571989369080" + } + } + ], + "videoOffsetTimeMsec": "3560750" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "Good morning my dear friends! This weekend jazz makes me relaxing. Very good music 😀🎹🥁" + } + ] + }, + "authorName": { + "simpleText": "Djordje Lainovic" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/--tbt3G2fVTk/AAAAAAAAAAI/AAAAAAAAAAA/w4oY17Qh4hc/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/--tbt3G2fVTk/AAAAAAAAAAI/AAAAAAAAAAA/w4oY17Qh4hc/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMDVxYldsMU16QjBkVlZEUmxSWVluZFJiMlJwWTI5RlRWRVNHME5QYmxjNE4xZ3dkSFZWUTBaU1NuazBRVzlrTmxSalFqRm5NQkFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTXpYMVpoUnpsNWFtaEtWM0F0V1dSMVJESmhTVTFS" + } + }, + "id": "CjkKGkNOam1pdTMwdHVVQ0ZUWGJ3UW9kaWNvRU1REhtDT25XODdYMHR1VUNGUkp5NEFvZDZUY0IxZzA%3D", + "timestampUsec": "1571989397615448", + "authorExternalChannelId": "UC3_VaG9yjhJWp-YduD2aIMQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "59:48" + } + } + }, + "clientId": "COnW87X0tuUCFRJy4Aod6TcB1g0" + } + } + ], + "videoOffsetTimeMsec": "3588722" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "Hi smile - smile 😊" + } + ] + }, + "authorName": { + "simpleText": "Waliyuddin sisila" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-TIoQvksTQlY/AAAAAAAAAAI/AAAAAAAAAAA/eOcRRQ--lZs/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-TIoQvksTQlY/AAAAAAAAAAI/AAAAAAAAAAA/eOcRRQ--lZs/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDVRWVhkUE56QjBkVlZEUmxwWFQzZFJiMlJLYW10RGJVRVNKME5RYlc5dlNYb3dkSFZWUTBaUmEwRXhVVzlrUTJWelRsUlJNVFUzTVRrNE9UTTVPVGsyT1JBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU0xUlhKUGFsZEhRMk5oVWxoNGJraE9jRVZVVWtKbg==" + } + }, + "id": "CkUKGkNOUGF3TzcwdHVVQ0ZaV093UW9kSmprQ21BEidDUG1vb0l6MHR1VUNGUWtBMVFvZENlc05UUTE1NzE5ODkzOTk5Njk%3D", + "timestampUsec": "1571989400595795", + "authorExternalChannelId": "UC5ErOjWGCcaRXxnHNpETRBg", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "59:52" + } + } + }, + "clientId": "CPmooIz0tuUCFQkA1QodCesNTQ1571989399969" + } + } + ], + "videoOffsetTimeMsec": "3592213" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "🙂" + } + ] + }, + "authorName": { + "simpleText": "Larry Jones" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-VKNGDODN-mg/AAAAAAAAAAI/AAAAAAAAAAA/2_ac0U2lQbE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-VKNGDODN-mg/AAAAAAAAAAI/AAAAAAAAAAA/2_ac0U2lQbE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2p3S09nb2FRMDVJVW5kZlJEQjBkVlZEUmxKWE0zZFJiMlJmVkRSQ1EzY1NIRU5QUTBRNGRISXdkSFZWUTBaaVRVSXhaMEZrVkZsUlExcEJMVEFRQUJvNEdnMEtDMU56YWtOdVNFOXJMVk5yS2ljS0dGVkRTbWhxUlRkM1ltUlpRV0ZsTVVjeU5XMHdkRWhCUVJJTFUzTnFRMjVJVDJzdFUyc2dBU2dCTWhvS0dGVkRNM1V0V2xCR1JYUTBPREkzWTFKSmFsUlVRWE5GWnclM0QlM0Q=" + } + }, + "id": "CjoKGkNOSFJ3X0QwdHVVQ0ZSVzN3UW9kX1Q0QkN3EhxDT0NEOHRyMHR1VUNGYk1CMWdBZFRZUUNaQS0w", + "timestampUsec": "1571989404838097", + "authorExternalChannelId": "UC3u-ZPFEt4827cRIjTTAsEg", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "59:55" + } + } + }, + "clientId": "COCD8tr0tuUCFbMB1gAdTYQCZA-0" + } + } + ], + "videoOffsetTimeMsec": "3595737" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "Good morning my dear friends! This weekend jazz makes me relaxing. Very good music 😀🎹🥁" + } + ] + }, + "authorName": { + "simpleText": "Djordje Lainovic" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/--tbt3G2fVTk/AAAAAAAAAAI/AAAAAAAAAAA/w4oY17Qh4hc/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/--tbt3G2fVTk/AAAAAAAAAAI/AAAAAAAAAAA/w4oY17Qh4hc/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMDlmU1cxZlZEQjBkVlZEUmxsTVpYZFJiMlF6YlVsR09IY1NHME5QYmxjNE4xZ3dkSFZWUTBaU1NuazBRVzlrTmxSalFqRm5NUkFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTXpYMVpoUnpsNWFtaEtWM0F0V1dSMVJESmhTVTFS" + } + }, + "id": "CjkKGkNPX0ltX1QwdHVVQ0ZZTGV3UW9kM21JRjh3EhtDT25XODdYMHR1VUNGUkp5NEFvZDZUY0IxZzE%3D", + "timestampUsec": "1571989412570223", + "authorExternalChannelId": "UC3_VaG9yjhJWp-YduD2aIMQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "1:00:04" + } + } + }, + "clientId": "COnW87X0tuUCFRJy4Aod6TcB1g1" + } + } + ], + "videoOffsetTimeMsec": "3604722" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "why so many japanese here?" + } + ] + }, + "authorName": { + "simpleText": "YYH" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-Kg1yNZLPpo4/AAAAAAAAAAI/AAAAAAAAAAA/KAKPCyTOSeM/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-Kg1yNZLPpo4/AAAAAAAAAAI/AAAAAAAAAAA/KAKPCyTOSeM/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMHhxWWpSZllqQjBkVlZEUmxGaFUzZFJiMlJ5ZFhkS1oxRVNHME5MYVVGNU5GUXdkSFZWUTBaVE1VUm9VVzlrYnpWdlJtOVJNQkFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTlBNMFpMTkRkVFoxSTBaMVpOYjJwcllYVkdWVTlu" + } + }, + "id": "CjkKGkNMamI0X2IwdHVVQ0ZRYVN3UW9kcnV3SmdREhtDS2lBeTRUMHR1VUNGUzFEaFFvZG81b0ZvUTA%3D", + "timestampUsec": "1571989417946552", + "authorExternalChannelId": "UCO3FK47SgR4gVMojkauFUOg", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "1:00:08" + } + } + }, + "clientId": "CKiAy4T0tuUCFS1DhQodo5oFoQ0" + } + } + ], + "videoOffsetTimeMsec": "3608795" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "ハロ" + } + ] + }, + "authorName": { + "simpleText": "Soixanteneuf" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-Bu3ItQBLq2U/AAAAAAAAAAI/AAAAAAAAAAA/29OhNljHYfk/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-Bu3ItQBLq2U/AAAAAAAAAAI/AAAAAAAAAAA/29OhNljHYfk/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMHg1TmpaSlNERjBkVlZEUmxWVWVYZFJiMlJXTjI5TldFRVNKME5QTWpBd1puSXdkSFZWUTBaamFEbGhRVzlrZERKalExSlJNVFUzTVRrNE9UUXpPVE0yT0JBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU5hZEZoU1JXZFdXRmhFU1dWUVpVRkdiR2RWVEhOQg==" + } + }, + "id": "CkUKGkNMeTY2SUgxdHVVQ0ZVVHl3UW9kVjdvTVhBEidDTzIwMGZyMHR1VUNGY2g5YUFvZHQyY0NSUTE1NzE5ODk0MzkzNjg%3D", + "timestampUsec": "1571989441092924", + "authorExternalChannelId": "UCZtXREgVXXDIePeAFlgULsA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "1:00:32" + } + } + }, + "clientId": "CO200fr0tuUCFch9aAodt2cCRQ1571989439368" + } + } + ], + "videoOffsetTimeMsec": "3632585" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatPlaceholderItemRenderer": { + "id": "CkUKGkNMT2NfSTcxdHVVQ0ZXdmhPQW9kbGRRSGVBEidDTzIwMGZyMHR1VUNGY2g5YUFvZHQyY0NSUTE1NzE5ODk0NjY5NzQ%3D", + "timestampUsec": "1571989468679731" + } + }, + "clientId": "CO200fr0tuUCFch9aAodt2cCRQ1571989466974" + } + } + ], + "videoOffsetTimeMsec": "3659848" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "Hello Japanese dear friends! 😀" + } + ] + }, + "authorName": { + "simpleText": "Djordje Lainovic" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/--tbt3G2fVTk/AAAAAAAAAAI/AAAAAAAAAAA/w4oY17Qh4hc/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/--tbt3G2fVTk/AAAAAAAAAAI/AAAAAAAAAAA/w4oY17Qh4hc/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMHBEUzNsd1NERjBkVlZEUm1FelVuZFJiMlJ3YTJOUGNWRVNHME5QYmxjNE4xZ3dkSFZWUTBaU1NuazBRVzlrTmxSalFqRm5NaEFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTXpYMVpoUnpsNWFtaEtWM0F0V1dSMVJESmhTVTFS" + } + }, + "id": "CjkKGkNKQ0t5cEgxdHVVQ0ZhM1J3UW9kcGtjT3FREhtDT25XODdYMHR1VUNGUkp5NEFvZDZUY0IxZzI%3D", + "timestampUsec": "1571989474149648", + "authorExternalChannelId": "UC3_VaG9yjhJWp-YduD2aIMQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "1:01:05" + } + } + }, + "clientId": "COnW87X0tuUCFRJy4Aod6TcB1g2" + } + } + ], + "videoOffsetTimeMsec": "3665409" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "私はこのチャンネルにいい音楽を聴くために来た" + } + ] + }, + "authorName": { + "simpleText": "まふまふ愛してる" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-N-nOAgLp_T0/AAAAAAAAAAI/AAAAAAAAAAA/k7O62ZS6xgE/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDF4YW1wd2NqRjBkVlZEUmxGbE9IZFJiMlJ2ZEVGT09XY1NKME5RYWswNFdtb3hkSFZWUTBaWFRrUm9VVzlrVm5OalJYQkJNVFUzTVRrNE9UUTVNVFExT1JBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU01TjBKaFJtOUVUekYxWTB0UE9YSkRUalJ2VVZaQg==" + } + }, + "id": "CkUKGkNNcWpqcHIxdHVVQ0ZRZTh3UW9kb3RBTjlnEidDUGpNOFpqMXR1VUNGV05EaFFvZFZzY0VwQTE1NzE5ODk0OTE0NTk%3D", + "timestampUsec": "1571989492044234", + "authorExternalChannelId": "UC97BaFoDO1ucKO9rCN4oQVA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "1:01:23" + } + } + }, + "clientId": "CPjM8Zj1tuUCFWNDhQodVscEpA1571989491459" + } + } + ], + "videoOffsetTimeMsec": "3683359" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "coz us japanese like jazz" + } + ] + }, + "authorName": { + "simpleText": "Soixanteneuf" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-Bu3ItQBLq2U/AAAAAAAAAAI/AAAAAAAAAAA/29OhNljHYfk/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-Bu3ItQBLq2U/AAAAAAAAAAI/AAAAAAAAAAA/29OhNljHYfk/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMHBJV0hoYWRqRjBkVlZEUmxwVVdYZFJiMlE0YkhkTFRYY1NKME5QTWpBd1puSXdkSFZWUTBaamFEbGhRVzlrZERKalExSlJNVFUzTVRrNE9UUTVNek0yTXhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU5hZEZoU1JXZFdXRmhFU1dWUVpVRkdiR2RWVEhOQg==" + } + }, + "id": "CkUKGkNKSFh4WnYxdHVVQ0ZaVFl3UW9kOGx3S013EidDTzIwMGZyMHR1VUNGY2g5YUFvZHQyY0NSUTE1NzE5ODk0OTMzNjM%3D", + "timestampUsec": "1571989495049105", + "authorExternalChannelId": "UCZtXREgVXXDIePeAFlgULsA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "1:01:26" + } + } + }, + "clientId": "CO200fr0tuUCFch9aAodt2cCRQ1571989493363" + } + } + ], + "videoOffsetTimeMsec": "3686141" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "ohhhhh naruhoto~" + } + ] + }, + "authorName": { + "simpleText": "YYH" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-Kg1yNZLPpo4/AAAAAAAAAAI/AAAAAAAAAAA/KAKPCyTOSeM/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-Kg1yNZLPpo4/AAAAAAAAAAI/AAAAAAAAAAA/KAKPCyTOSeM/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMHhFTkhaaE56RjBkVlZEUmxNelZYZFJiMlJuVDFGR1ZrRVNHME5MYVVGNU5GUXdkSFZWUTBaVE1VUm9VVzlrYnpWdlJtOVJNUkFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTlBNMFpMTkRkVFoxSTBaMVpOYjJwcllYVkdWVTlu" + } + }, + "id": "CjkKGkNMRDR2YTcxdHVVQ0ZTM1V3UW9kZ09RRlZBEhtDS2lBeTRUMHR1VUNGUzFEaFFvZG81b0ZvUTE%3D", + "timestampUsec": "1571989534768176", + "authorExternalChannelId": "UCO3FK47SgR4gVMojkauFUOg", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "1:02:06" + } + } + }, + "clientId": "CKiAy4T0tuUCFS1DhQodo5oFoQ1" + } + } + ], + "videoOffsetTimeMsec": "3726156" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "we meet again mafumafu san" + } + ] + }, + "authorName": { + "simpleText": "Soixanteneuf" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-Bu3ItQBLq2U/AAAAAAAAAAI/AAAAAAAAAAA/29OhNljHYfk/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-Bu3ItQBLq2U/AAAAAAAAAAI/AAAAAAAAAAA/29OhNljHYfk/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2tjS1JRb2FRMDVoZFRaaVJERjBkVlZEUmxVelkzZFJiMlIxY1hkTmFrRVNKME5QTWpBd1puSXdkSFZWUTBaamFEbGhRVzlrZERKalExSlJNVFUzTVRrNE9UVXpOemszTnhBQUdqZ2FEUW9MVTNOcVEyNUlUMnN0VTJzcUp3b1lWVU5LYUdwRk4zZGlaRmxCWVdVeFJ6STFiVEIwU0VGQkVndFRjMnBEYmtoUGF5MVRheUFCS0FFeUdnb1lWVU5hZEZoU1JXZFdXRmhFU1dWUVpVRkdiR2RWVEhOQg==" + } + }, + "id": "CkUKGkNOYXU2YkQxdHVVQ0ZVM2N3UW9kdXF3TWpBEidDTzIwMGZyMHR1VUNGY2g5YUFvZHQyY0NSUTE1NzE5ODk1Mzc5Nzc%3D", + "timestampUsec": "1571989539673942", + "authorExternalChannelId": "UCZtXREgVXXDIePeAFlgULsA", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "1:02:11" + } + } + }, + "clientId": "CO200fr0tuUCFch9aAodt2cCRQ1571989537977" + } + } + ], + "videoOffsetTimeMsec": "3731100" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "World is great! Be happy!🌍🌎🌏 😁😀" + } + ] + }, + "authorName": { + "simpleText": "Djordje Lainovic" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/--tbt3G2fVTk/AAAAAAAAAAI/AAAAAAAAAAA/w4oY17Qh4hc/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/--tbt3G2fVTk/AAAAAAAAAAI/AAAAAAAAAAA/w4oY17Qh4hc/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMHRYVG5aaVNERjBkVlZEUm1OaWVuZFJiMlJzVGtGTFptY1NHME5QYmxjNE4xZ3dkSFZWUTBaU1NuazBRVzlrTmxSalFqRm5NeEFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTXpYMVpoUnpsNWFtaEtWM0F0V1dSMVJESmhTVTFS" + } + }, + "id": "CjkKGkNLV052YkgxdHVVQ0ZjYnp3UW9kbE5BS2ZnEhtDT25XODdYMHR1VUNGUkp5NEFvZDZUY0IxZzM%3D", + "timestampUsec": "1571989541045925", + "authorExternalChannelId": "UC3_VaG9yjhJWp-YduD2aIMQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "1:02:12" + } + } + }, + "clientId": "COnW87X0tuUCFRJy4Aod6TcB1g3" + } + } + ], + "videoOffsetTimeMsec": "3732472" + } + }, + { + "replayChatItemAction": { + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "because everybody love good music" + } + ] + }, + "authorName": { + "simpleText": "Svatopluk Čech" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/-4PqtNbyI02Q/AAAAAAAAAAI/AAAAAAAAAAA/UCO9qZGm8t8/s32-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/-4PqtNbyI02Q/AAAAAAAAAAI/AAAAAAAAAAA/UCO9qZGm8t8/s64-c-k-no-mo-rj-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2pzS09Rb2FRMDFZWVhNM2FqRjBkVlZEUmxNek5IZFJiMlJZWVhkSFdtY1NHME5QWVhadlgxaDVkSFZWUTBaVlpVUkdVVzlrTTFSRlEwVkJNQkFBR2pnYURRb0xVM05xUTI1SVQyc3RVMnNxSndvWVZVTkthR3BGTjNkaVpGbEJZV1V4UnpJMWJUQjBTRUZCRWd0VGMycERia2hQYXkxVGF5QUJLQUV5R2dvWVZVTlljRVpFU2xJdGFYYzNUbEZmYm1KcU0zZDRNR05S" + } + }, + "id": "CjkKGkNNWGFzN2oxdHVVQ0ZTMzR3UW9kWGF3R1pnEhtDT2F2b19YeXR1VUNGVWVERlFvZDNURUNFQTA%3D", + "timestampUsec": "1571989555572037", + "authorExternalChannelId": "UCXpFDJR-iw7NQ_nbj3wx0cQ", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampText": { + "simpleText": "1:02:27" + } + } + }, + "clientId": "COavo_XytuUCFUeDFQod3TECEA0" + } + } + ], + "videoOffsetTimeMsec": "3747045" + } + } + ] + } + } + }, + "csn": "CAXIXa-uHZnC4wL5nZ7oBQ", + "url": "\/live_chat_replay\/get_live_chat_replay?continuation=op2w0wRyGjxDZzhhRFFvTFUzTnFRMjVJVDJzdFUyc2FFLXFvM2JrQkRRb0xVM05xUTI1SVQyc3RVMnNnQVElM0QlM0QoATAAOABAAEgEUhwIABAAGAAgACoOc3RhdGljY2hlY2tzdW1AAFgDYAFoAHIECAEQAHgA", + "xsrf_token": "QUFFLUhqbTZWWEFiT3ZxaDAtY09pRzZXSUotZC1uclFMQXxBQ3Jtc0tsOFZYN09CWFlBd2NKSFB4R3hmN3dUY2xXaW9tbzdFZlZBTllDcnBhMG9WUXVkZGZ5RGRIYkxSajBiNVpsNU5PV3hNYkhUZGJybTVEYWM2MWREbTRUYnc3XzRpeUJVbFpNR0dod1RPbGtVLWJhdkhtUVpVN0JKVGNSQVRSY0ZsODhodEwxaWdjN0pHZThlbEJVXzJMc2VXZGtQOXc=" +} \ No newline at end of file