AI 移行 #38

マージ済み
みてるぞ が 49 個のコミットを ai-migration から main へマージ 2025-12-03 02:02:36 +09:00
コミット 37c9947d4a の変更だけを表示してゐます - すべてのコミットを表示
+130 -35
ファイルの表示
@@ -8,16 +8,19 @@ import wave
from datetime import datetime, timedelta
from enum import Enum, auto
from typing import Callable, TypedDict
from io import BytesIO
import cv2
import emoji
import ephem
import numpy as np
import pygame
import pygame.gfxdraw
import pytchat
import requests
from cv2 import VideoCapture
from ephem import Moon, Observer, Sun
from pydub import AudioSegment
from pygame import Rect, Surface
from pygame.font import Font
from pygame.mixer import Sound
@@ -50,6 +53,7 @@ def main (
x = CWindow.WIDTH * 3 / 4,
y = CWindow.HEIGHT - 120,
balloon = balloon)
Video (game, 'snack_time.mp4').play ()
CurrentTime (game, SYSTEM_FONT)
try:
broadcast = Broadcast (os.environ['BROADCAST_CODE'])
@@ -639,16 +643,6 @@ class Jojoko (GameObject):
def redraw (
self,
) -> None:
if self.frame % (FPS * 3600) == 0:
self.surface = self._get_surface ()
surface = pygame.transform.rotate (self.surface, -(90 + math.degrees (self.arg)))
surface.set_colorkey ((0, 255, 0))
self.game.screen.blit (surface, surface.get_rect (center = (self.x, self.y)))
super ().redraw ()
def update (
self,
) -> None:
self.moon.compute (self.game.sky.observer)
self.alt = self.moon.alt
@@ -657,7 +651,12 @@ class Jojoko (GameObject):
self.arg = self.new_arg
self.x = self.new_x
self.y = self.new_y
super ().update ()
if self.frame % (FPS * 3600) == 0:
self.surface = self._get_surface ()
surface = pygame.transform.rotate (self.surface, -(90 + math.degrees (self.arg)))
surface.set_colorkey ((0, 255, 0))
self.game.screen.blit (surface, surface.get_rect (center = (self.x, self.y)))
super ().redraw ()
@property
def phase (
@@ -732,30 +731,6 @@ class CWindow:
HEIGHT = 768
def get_surfaces_from_video (
video_path: str,
) -> list[Surface]:
cap = VideoCapture (video_path)
if not cap.isOpened ():
return []
fps = cap.get (cv2.CAP_PROP_FPS)
surfaces: list[Surface] = []
while cap.isOpened ():
(ret, frame) = cap.read ()
if not ret:
break
frame = cv2.cvtColor (frame, cv2.COLOR_BGR2RGB)
frame_surface = pygame.surfarray.make_surface (frame)
frame_surface = pygame.transform.rotate (frame_surface, -90)
surfaces.append (pygame.transform.flip (frame_surface, True, False))
cap.release ()
return surfaces
class Broadcast:
chat: PytchatCore
@@ -777,6 +752,126 @@ class Broadcast:
return random.choice (chats)
class NicoVideo (Video):
...
class Video (GameObject):
fps: int
pausing: bool = False
sound: Sound
surfaces: list[Surface]
def __init__ (
self,
game: Game,
path: str,
):
super ().__init__ (game)
self.pausing = False
(self.surfaces, self.fps) = self._create_surfaces (path)
self.sound = self._create_sound (path)
self.stop ()
def _create_sound (
self,
path: str,
) -> Sound:
bytes_io = BytesIO ()
audio = AudioSegment.from_file (path, format = path.split ('.')[-1])
audio.export (bytes_io, format = 'wav')
bytes_io.seek (0)
return pygame.mixer.Sound (bytes_io)
def _create_surfaces (
self,
path: str,
) -> tuple[list[Surface], int]:
cap = self._load (path)
surfaces: list[Surface] = []
if cap is None:
return ([], FPS)
fps = int (cap.get (cv2.CAP_PROP_FPS))
while cap.isOpened ():
frame = self._read_frame (cap)
if frame is None:
break
surfaces.append (self._convert_to_surface (frame))
new_surfaces: list[Surface] = []
for i in range (len (surfaces) * FPS // fps):
new_surfaces.append (surfaces[i * fps // FPS])
return (new_surfaces, fps)
def _load (
self,
path: str,
) -> VideoCapture | None:
"""
OpenCV で動画を読込む.
"""
cap = VideoCapture (path)
if cap.isOpened ():
return cap
return None
def _read_frame (
self,
cap: VideoCapture,
) -> np.ndarray | None:
"""
動画のフレームを読込む.
"""
ret: bool
frame: np.ndarray
(ret, frame) = cap.read ()
if ret:
return frame
return None
def _convert_to_surface (
self,
frame: np.ndarray,
) -> Surface:
frame = cv2.cvtColor (frame, cv2.COLOR_BGR2RGB)
frame_surface = pygame.surfarray.make_surface (frame)
frame_surface = pygame.transform.rotate (frame_surface, -90)
frame_surface = pygame.transform.flip (frame_surface, True, False)
return frame_surface
def play (
self,
) -> None:
self.enabled = True
self.pausing = False
self.sound.play ()
def stop (
self,
) -> None:
self.enabled = False
self.frame = 0
def pause (
self,
) -> None:
self.pausing = True
def redraw (
self,
) -> None:
self.game.screen.blit (self.surfaces[self.frame], (self.x, self.y))
super ().redraw ()
def update (
self,
) -> None:
if self.frame >= len (self.surfaces) - 1:
self.pause ()
if self.pausing:
self.frame -= 1
super ().update ()
def fetch_bytes_from_url (
url: str,
) -> bytes | None: