aboutsummaryrefslogtreecommitdiffstats
path: root/yt_livechat_stats.py
diff options
context:
space:
mode:
Diffstat (limited to 'yt_livechat_stats.py')
-rw-r--r--yt_livechat_stats.py92
1 files changed, 68 insertions, 24 deletions
diff --git a/yt_livechat_stats.py b/yt_livechat_stats.py
index 6e6e172..9846b5b 100644
--- a/yt_livechat_stats.py
+++ b/yt_livechat_stats.py
@@ -4,6 +4,7 @@ import argparse
import curses
from text_renderer import TextRenderer
from data_writer import DataWriter
+from vod_parser import VodParser
import yt_dlp
import os
@@ -11,6 +12,7 @@ import os
class StreamEndedError(Exception):
pass
+
def get_message_rate(message_count: int, last_refresh_time: time.time) -> tuple:
if time.time() - last_refresh_time < 1:
return "", None
@@ -20,11 +22,14 @@ def get_message_rate(message_count: int, last_refresh_time: time.time) -> tuple:
message_data = message_rate_text, message_count/time_elapsed
return message_data
+
def check_for_superchats(chat_data, data_writer: DataWriter):
if chat_data.amountValue:
- data_writer.write(f"Superchat: {chat_data.amountValue} from {chat_data.author.name}\n")
+ data_writer.write(
+ f"Superchat: {chat_data.amountValue} from {chat_data.author.name}\n")
data_writer.write(f"Message: {chat_data.message}\n\n")
+
def get_video_info(video_id: str) -> dict:
with yt_dlp.YoutubeDL() as ydl:
info = ydl.extract_info(video_id, download=False)
@@ -37,9 +42,18 @@ def main(stdscr, video_id: str, args: argparse.Namespace):
data_writer = DataWriter(f"{video_id}-analytics.txt")
video_info = get_video_info(video_id)
stream_start_unix_time = video_info["release_timestamp"]
-
-
-
+ if not bool(video_info["is_live"]):
+ vod_parser = VodParser(video_id, data_writer,
+ start_unix_time=stream_start_unix_time,
+ theshold=args.threshold,
+ cooldown=args.cooldown,
+ keywords=args.keywords)
+ vod_parser.download_live_chat()
+ vod_parser.parse_chat()
+ vod_parser.clean_up()
+ exit()
+ if args.keywords:
+ keywords = [keyword.strip() for keyword in args.keywords.split(",")]
message_count = 0
on_cooldown = False
cooldown_start_time = time.time()
@@ -52,51 +66,81 @@ def main(stdscr, video_id: str, args: argparse.Namespace):
key = stdscr.getch()
if key == ord('q'):
raise Exception("User ended data collection")
- timestamp_since_start = time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time_const))
- info_msg = "Now collecting data for " + video_id + " Elapsed time: " + timestamp_since_start + " seconds (Press q to quit)"
+ timestamp_since_start = time.strftime(
+ "%H:%M:%S", time.gmtime(time.time() - start_time_const))
+ info_msg = "Now collecting data for " + video_id + " Elapsed time: " + \
+ timestamp_since_start + " seconds (Press q to quit)"
vid_info = f"Title: {video_info['title']} Channel: {video_info['uploader']} \nUnix Start Time: {stream_start_unix_time}"
text_renderer.render(info_msg, y_pos=0)
text_renderer.render(vid_info, y_pos=1)
if on_cooldown and time.time() - cooldown_start_time > args.cooldown:
on_cooldown = False
-
+
# Message Rate Related Features
if time.time() - last_refresh_time > 1 and not on_cooldown:
- message_rate_text, message_rate = get_message_rate(message_count, last_refresh_time)
+ message_rate_text, message_rate = get_message_rate(
+ message_count, last_refresh_time)
text_renderer.render(message_rate_text, y_pos=4)
last_refresh_time = time.time()
if message_rate > args.threshold:
diff_time_seconds = time.time() - stream_start_unix_time
- youtube_timestamp = time.strftime("%H:%M:%S", time.gmtime(diff_time_seconds))
- data_writer.write(f"Notable moment found at {youtube_timestamp} measured at {message_rate}\n")
- text_renderer.render(f"Latest notable moment found at {youtube_timestamp} measured at {message_rate} - on cooldown until {time.time() + args.cooldown}\n", y_pos=5)
+ youtube_timestamp = time.strftime(
+ "%H:%M:%S", time.gmtime(diff_time_seconds))
+ data_writer.write(
+ f"Notable moment found at {youtube_timestamp} measured at {message_rate}\n")
+ text_renderer.render(
+ f"Latest notable moment found at {youtube_timestamp} measured at {message_rate} - on cooldown until {time.time() + args.cooldown}\n", y_pos=5)
on_cooldown = True
message_count = 0
else:
message_count += 1
+ # Keyword related features
+ if args.keywords:
+ for keyword in keywords:
+ if keyword.lower() in chat_data.message.lower():
+ diff_time_seconds = time.time() - stream_start_unix_time
+ youtube_timestamp = time.strftime(
+ "%H:%M:%S", time.gmtime(diff_time_seconds))
+ data_writer.write(
+ f"Keyword {keyword} found at {youtube_timestamp}\n")
+ text_renderer.render(
+ f"Keyword {keyword} found at {youtube_timestamp}\n", y_pos=6)
+ on_cooldown = True
+ cooldown_start_time = time.time()
+
# Superchat Related Features (TODO)
- #if args.superchats:
+ # if args.superchats:
# check_for_superchats(chat_data, data_writer)
-
- text_renderer.render(get_message_rate(message_count, last_refresh_time)[0], y_pos=2)
+ text_renderer.render(get_message_rate(
+ message_count, last_refresh_time)[0], y_pos=2)
if args.show_chat:
- text_renderer.log_message("[Chat]" + chat_data.author.name + ": " + chat_data.message)
+ text_renderer.log_message(
+ "[Chat]" + chat_data.author.name + ": " + chat_data.message)
text_renderer.refresh()
-
+
except Exception as e:
- data_writer.write(f"Data collection ended at {time.strftime('%H:%M:%S', time.gmtime(time.time() - stream_start_unix_time))} due to {e}\n")
+ data_writer.write(
+ f"Data collection ended at {time.strftime('%H:%M:%S', time.gmtime(time.time() - stream_start_unix_time))} due to {e}\n")
+
if __name__ == "__main__":
- parser = argparse.ArgumentParser(description='YouTube Live Chat Message Rate Tracker')
- parser.add_argument('video_id', help='The ID of the YouTube video for the live chat')
- parser.add_argument('--show-chat', action='store_true', help='Show the live chat in the terminal window')
- parser.add_argument('--superchats', action='store_true', help='Log superchat messages and amounts')
- parser.add_argument('--threshold', type=int, default=5, help='Log timestamps when the message rate exceeds this value (msg/s)')
- parser.add_argument('--keywords', type=str, help='Log timestamps when a message contains any of these keywords. Enter keywords separated by commas')
- parser.add_argument('--cooldown', type=int, default=20, help='Minimum time that must pass before another notable moment is logged (in seconds)')
+ parser = argparse.ArgumentParser(
+ description='YouTube Live Chat Message Rate Tracker')
+ parser.add_argument(
+ 'video_id', help='The ID of the YouTube video for the live chat')
+ parser.add_argument('--show-chat', action='store_true',
+ help='Show the live chat in the terminal window')
+ parser.add_argument('--superchats', action='store_true',
+ help='Log superchat messages and amounts')
+ parser.add_argument('--threshold', type=int, default=5,
+ help='Log timestamps when the message rate exceeds this value (msg/s)')
+ parser.add_argument('--keywords', type=str,
+ help='Log timestamps when a message contains any of these keywords. Enter keywords separated by commas')
+ parser.add_argument('--cooldown', type=int, default=20,
+ help='Minimum time that must pass before another notable moment is logged (in seconds)')
args = parser.parse_args()
if os.path.exists(f"{args.video_id}-analytics.txt"):
if input(f"File {args.video_id}-analytics.txt already exists. Overwrite? (y/n): ").lower() != "y":
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage