このコミットが含まれているのは:
@@ -857,7 +857,10 @@ class Broadcast:
|
||||
|
||||
|
||||
class Video (GameObject):
|
||||
cap: VideoCapture | None
|
||||
current: Surface | None
|
||||
fps: int
|
||||
path: str
|
||||
pausing: bool = False
|
||||
sound: Sound | None
|
||||
surfaces: list[Surface]
|
||||
@@ -868,11 +871,59 @@ class Video (GameObject):
|
||||
path: str,
|
||||
):
|
||||
super ().__init__ (game)
|
||||
self.pausing = False
|
||||
(self.surfaces, self.fps) = self._create_surfaces (path)
|
||||
self.path = path
|
||||
self.cap = None
|
||||
self.current = None
|
||||
self.sound = self._create_sound (path)
|
||||
self.stop ()
|
||||
|
||||
def play (
|
||||
self,
|
||||
) -> None:
|
||||
self.enabled = True
|
||||
self.cap = VideoCapture (self.path)
|
||||
self.frame = 0
|
||||
if self.sound:
|
||||
self.sound.play ()
|
||||
|
||||
def stop (
|
||||
self,
|
||||
) -> None:
|
||||
self.enabled = False
|
||||
self.frame = 0
|
||||
if self.cap:
|
||||
self.cap.release ()
|
||||
self.cap = None
|
||||
|
||||
def redraw (
|
||||
self,
|
||||
) -> None:
|
||||
if (not self.enabled) or (self.cap is None):
|
||||
return
|
||||
ret, frame = self.cap.read ()
|
||||
if not ret:
|
||||
self.stop ()
|
||||
return
|
||||
surf = self._convert_to_surface (frame)
|
||||
surf = pygame.transform.scale (surf, (self.width, self.height))
|
||||
self.game.screen.blit (surf, (self.x, self.y))
|
||||
super ().redraw ()
|
||||
|
||||
def update (
|
||||
self,
|
||||
) -> None:
|
||||
super ().update ()
|
||||
|
||||
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 _create_sound (
|
||||
self,
|
||||
path: str,
|
||||
@@ -887,96 +938,6 @@ class Video (GameObject):
|
||||
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
|
||||
if self.sound is not None:
|
||||
self.sound.play ()
|
||||
|
||||
def stop (
|
||||
self,
|
||||
) -> None:
|
||||
self.enabled = False
|
||||
self.frame = 0
|
||||
|
||||
def pause (
|
||||
self,
|
||||
) -> None:
|
||||
self.pausing = True
|
||||
|
||||
def redraw (
|
||||
self,
|
||||
) -> None:
|
||||
surface = pygame.transform.scale (self.surfaces[self.frame], (self.width, self.height))
|
||||
self.game.screen.blit (surface, (self.x, self.y))
|
||||
super ().redraw ()
|
||||
|
||||
def update (
|
||||
self,
|
||||
) -> None:
|
||||
if self.frame >= len (self.surfaces) - 1:
|
||||
self.stop ()
|
||||
if self.pausing:
|
||||
self.frame -= 1
|
||||
super ().update ()
|
||||
|
||||
|
||||
class NicoVideo (Video):
|
||||
def __init__ (
|
||||
|
||||
新しい課題から参照
ユーザをブロックする