Browse Source

#34 動画再生可能に

ai-migration
みてるぞ 2 weeks ago
parent
commit
37c9947d4a
1 changed files with 130 additions and 35 deletions
  1. +130
    -35
      test.py

+ 130
- 35
test.py View File

@@ -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:


Loading…
Cancel
Save