|
|
|
@@ -11,7 +11,7 @@ import wave |
|
|
|
from datetime import datetime, timedelta |
|
|
|
from enum import Enum, auto |
|
|
|
from io import BytesIO |
|
|
|
from typing import Callable, TypedDict, cast |
|
|
|
from typing import Any, Callable, TypedDict, cast |
|
|
|
|
|
|
|
import cv2 |
|
|
|
import emoji |
|
|
|
@@ -30,8 +30,10 @@ from pygame.time import Clock |
|
|
|
from pytchat.core.pytchat import PytchatCore |
|
|
|
from pytchat.processors.default.processor import Chat |
|
|
|
|
|
|
|
import video |
|
|
|
from aques import Aques |
|
|
|
from common_module import CommonModule |
|
|
|
from niconico import NicoNico |
|
|
|
from nizika_ai.config import DB |
|
|
|
from nizika_ai.consts import Character, GPTModel, Platform, QueryType |
|
|
|
from nizika_ai.models import Answer, AnsweredFlag, Query, User |
|
|
|
@@ -59,6 +61,8 @@ def main ( |
|
|
|
y = CWindow.HEIGHT - 56.25, |
|
|
|
balloon = balloon) |
|
|
|
snack_time = SnackTime (game) |
|
|
|
nico_video = NicoVideo (game) |
|
|
|
nico_video_layer = nico_video.layer |
|
|
|
CurrentTime (game, DEERJIKA_FONT) |
|
|
|
|
|
|
|
broadcast: Broadcast | None = None |
|
|
|
@@ -79,13 +83,14 @@ def main ( |
|
|
|
pygame.quit () |
|
|
|
sys.exit () |
|
|
|
|
|
|
|
if (not balloon.enabled) and (not snack_time.enabled): |
|
|
|
if ((not balloon.enabled) |
|
|
|
and (not snack_time.enabled) |
|
|
|
and (not nico_video.enabled)): |
|
|
|
if waiting_balloon[0]: |
|
|
|
deerjika.talk (waiting_balloon[1], waiting_balloon[2]) |
|
|
|
if waiting_balloon[2] == WATCHING_MSG: |
|
|
|
... |
|
|
|
else: |
|
|
|
waiting_balloon = (False, '', '') |
|
|
|
nico_video.play () |
|
|
|
waiting_balloon = (False, '', '') |
|
|
|
|
|
|
|
if now_m - last_flags_poll >= 1: |
|
|
|
last_flags_poll = now_m |
|
|
|
@@ -117,6 +122,8 @@ def main ( |
|
|
|
query = Query.find (answer.query_id) |
|
|
|
deerjika.talk (None, answer.content) |
|
|
|
waiting_balloon = (True, None, WATCHING_MSG) |
|
|
|
nico_video = NicoVideo (game, query.transfer_data.get ('video_code')) |
|
|
|
nico_video.layer = nico_video_layer |
|
|
|
answer_flag.answered = True |
|
|
|
answer_flag.save () |
|
|
|
case _: |
|
|
|
@@ -975,10 +982,19 @@ class NicoVideo (Video): |
|
|
|
def __init__ ( |
|
|
|
self, |
|
|
|
game: Game, |
|
|
|
video_code: str, |
|
|
|
video_code: str | None = None, |
|
|
|
): |
|
|
|
comments = fetch_comments (video_code) |
|
|
|
#super ().__init__ (game, ) |
|
|
|
if video_code is None: |
|
|
|
super ().__init__ (game, './assets/snack_time.mp4') |
|
|
|
else: |
|
|
|
try: |
|
|
|
comments = fetch_comments (video_code) |
|
|
|
fetch_nico_video (video_code, comments) |
|
|
|
super ().__init__ (game, './outputs/output.mp4') |
|
|
|
except Exception: |
|
|
|
super ().__init__ (game, './assets/snack_time.mp4') |
|
|
|
(self.width, self.height) = (CWindow.HEIGHT * 16 // 9, CWindow.HEIGHT) |
|
|
|
(self.x, self.y) = ((CWindow.WIDTH - self.width) / 2, 0) |
|
|
|
|
|
|
|
|
|
|
|
class SnackTime (Video): |
|
|
|
@@ -1000,6 +1016,37 @@ def fetch_bytes_from_url ( |
|
|
|
return res.content |
|
|
|
|
|
|
|
|
|
|
|
def fetch_nico_video ( |
|
|
|
video_code: str, |
|
|
|
comments: list[CommentDict], |
|
|
|
) -> None: |
|
|
|
client = NicoNico () |
|
|
|
|
|
|
|
watch_data = client.video.watch.get_watch_data (video_code) |
|
|
|
|
|
|
|
outputs = client.video.watch.get_outputs (watch_data) |
|
|
|
output_label = next (iter (outputs)) |
|
|
|
|
|
|
|
downloaded_path = client.video.watch.download_video ( |
|
|
|
watch_data, output_label, '%(title)s.%(ext)s') |
|
|
|
os.rename (downloaded_path, './outputs/base.mp4') |
|
|
|
|
|
|
|
ass = video.build_ass (cast (Any, comments), 640, 480) |
|
|
|
with open ('./outputs/comments.ass', 'w', encoding = 'utf-8') as f: |
|
|
|
f.write (ass) |
|
|
|
|
|
|
|
subprocess.run ( |
|
|
|
['ffmpeg', |
|
|
|
'-i', './outputs/base.mp4', |
|
|
|
'-vf', 'ass=./outputs/comments.ass', |
|
|
|
'-c:v', 'libx264', |
|
|
|
'-crf', '18', |
|
|
|
'-preset', 'veryfast', |
|
|
|
'-c:a', 'copy', |
|
|
|
'./outputs/output.mp4'], |
|
|
|
check = True) |
|
|
|
|
|
|
|
|
|
|
|
def fetch_comments ( |
|
|
|
video_code: str, |
|
|
|
) -> list[CommentDict]: |
|
|
|
@@ -1011,6 +1058,7 @@ def fetch_comments ( |
|
|
|
text = True) |
|
|
|
return cast(list[CommentDict], json.loads (result.stdout)) |
|
|
|
|
|
|
|
|
|
|
|
def add_query ( |
|
|
|
broadcast: Broadcast, |
|
|
|
) -> None: |
|
|
|
|