posedet/audio_player.py

108 lines
3.4 KiB
Python

import os
import time
import tempfile
import streamlit as st
from config import PYGAME_AVAILABLE, MOVIEPY_AVAILABLE
if PYGAME_AVAILABLE:
import pygame
if MOVIEPY_AVAILABLE:
from moviepy import VideoFileClip
class AudioPlayer:
"""A class to handle audio extraction and playback for the video."""
def __init__(self):
self.is_playing = False
self.audio_file = None
self.start_time = None
self.pygame_initialized = False
if PYGAME_AVAILABLE:
try:
# Initialize pygame mixer with a specific frequency to avoid common issues
pygame.mixer.pre_init(frequency=44100, size=-16, channels=2, buffer=512)
pygame.mixer.init()
self.pygame_initialized = True
except Exception as e:
st.warning(f"Audio mixer initialization failed: {e}")
def extract_audio_from_video(self, video_path):
"""Extracts audio from a video file using MoviePy."""
if not MOVIEPY_AVAILABLE or not self.pygame_initialized:
return None
try:
temp_audio = tempfile.mktemp(suffix='.wav')
video_clip = VideoFileClip(video_path)
if video_clip.audio is not None:
video_clip.audio.write_audiofile(temp_audio, logger=None)
video_clip.close()
return temp_audio
else:
video_clip.close()
return None
except Exception as e:
st.warning(f"Could not extract audio: {e}")
return None
def load_audio(self, video_path):
"""Loads an audio file for playback."""
if not self.pygame_initialized:
return False
try:
audio_file = self.extract_audio_from_video(video_path)
if audio_file and os.path.exists(audio_file):
self.audio_file = audio_file
return True
return False
except Exception as e:
st.error(f"Failed to load audio: {e}")
return False
def play(self):
"""Plays the loaded audio file."""
if not self.pygame_initialized or not self.audio_file or self.is_playing:
return False
try:
pygame.mixer.music.load(self.audio_file)
pygame.mixer.music.play()
self.is_playing = True
self.start_time = time.time()
return True
except Exception as e:
st.warning(f"Audio playback failed: {e}")
return False
def stop(self):
"""Stops the audio playback."""
if self.pygame_initialized and self.is_playing:
try:
pygame.mixer.music.stop()
self.is_playing = False
return True
except Exception as e:
return False
return False
def restart(self):
"""Restarts the audio from the beginning."""
if self.pygame_initialized and self.audio_file:
self.stop()
# Small delay to ensure proper stopping
time.sleep(0.1)
return self.play()
return False
def cleanup(self):
"""Cleans up audio resources."""
self.stop()
if self.audio_file and os.path.exists(self.audio_file):
try:
os.unlink(self.audio_file)
self.audio_file = None
except Exception:
pass