About to restructure voicebot to support dynamic agent loading
This commit is contained in:
parent
1ba48bdc79
commit
93025d22fc
44
Dockerfile.python-3.12
Normal file
44
Dockerfile.python-3.12
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
FROM ubuntu:plucky
|
||||||
|
|
||||||
|
# Install build dependencies and tools
|
||||||
|
RUN apt-get update \
|
||||||
|
&& DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
||||||
|
build-essential \
|
||||||
|
checkinstall \
|
||||||
|
zlib1g-dev \
|
||||||
|
libncurses5-dev \
|
||||||
|
libgdbm-dev \
|
||||||
|
libnss3-dev \
|
||||||
|
libssl-dev \
|
||||||
|
libreadline-dev \
|
||||||
|
libffi-dev \
|
||||||
|
libsqlite3-dev \
|
||||||
|
libbz2-dev \
|
||||||
|
tk-dev \
|
||||||
|
liblzma-dev \
|
||||||
|
wget \
|
||||||
|
tar \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/{apt,dpkg,cache,log}
|
||||||
|
|
||||||
|
# Download Python 3.12.11 source
|
||||||
|
RUN wget https://www.python.org/ftp/python/3.12.11/Python-3.12.11.tgz -O /tmp/Python-3.12.11.tgz \
|
||||||
|
&& tar -xvf /tmp/Python-3.12.11.tgz -C /tmp \
|
||||||
|
&& rm /tmp/Python-3.12.11.tgz
|
||||||
|
|
||||||
|
# Change to source directory
|
||||||
|
WORKDIR /tmp/Python-3.12.11
|
||||||
|
|
||||||
|
# Configure the build
|
||||||
|
RUN ./configure --enable-optimizations --enable-shared --prefix=/usr
|
||||||
|
|
||||||
|
# Compile
|
||||||
|
RUN make -j $(nproc)
|
||||||
|
|
||||||
|
RUN make altinstall DESTDIR=/tmp/python-build \
|
||||||
|
&& mkdir -p /tmp/python-build/DEBIAN \
|
||||||
|
&& echo "Package: python3.12-custom\nVersion: 3.12.11-1\nSection: custom\nPriority: optional\nArchitecture: amd64\nMaintainer: you@example.com\nDescription: Custom Python 3.12.11 build" > /tmp/python-build/DEBIAN/control \
|
||||||
|
&& dpkg-deb --build /tmp/python-build /python3.12-custom_3.12.11-1_amd64.deb \
|
||||||
|
&& rm -rf /tmp/python-build
|
||||||
|
|
||||||
|
CMD ["/bin/bash", "-c", "cp /python3.12-custom_3.12.11-1_*.deb /build/"]
|
17
README.md
17
README.md
@ -298,6 +298,23 @@ The backend acts as the signaling server, routing WebRTC negotiation messages be
|
|||||||
|
|
||||||
## Development Tools
|
## Development Tools
|
||||||
|
|
||||||
|
### Python version
|
||||||
|
|
||||||
|
Many of the packages required for ML are not available or with correct versions
|
||||||
|
with Python 3.13 (default for Ubuntu:Plucky.) If your host is running
|
||||||
|
python>3.12 and there aren't any python-3.12 packages available to install, you
|
||||||
|
can use the 'python-3.12' container to build a python3.12 package:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Build the .deb
|
||||||
|
docker compose build python-3.12
|
||||||
|
# Copy the .deb from the container image to ./build
|
||||||
|
docker compose run python-3.12
|
||||||
|
# Install the pkg:
|
||||||
|
sudo dpkg -i build/python*.deb
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### TypeScript Type Generation
|
### TypeScript Type Generation
|
||||||
The project includes automatic TypeScript type generation from the FastAPI OpenAPI schema:
|
The project includes automatic TypeScript type generation from the FastAPI OpenAPI schema:
|
||||||
|
|
||||||
|
@ -18,6 +18,17 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- ai-voicebot-net
|
- ai-voicebot-net
|
||||||
|
|
||||||
|
python-3.12:
|
||||||
|
container_name: python-3.12
|
||||||
|
hostname: python-3.12
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.python-3.12
|
||||||
|
restart: no
|
||||||
|
volumes:
|
||||||
|
- ./build:/build:rw
|
||||||
|
|
||||||
|
|
||||||
server:
|
server:
|
||||||
container_name: server
|
container_name: server
|
||||||
hostname: server
|
hostname: server
|
||||||
|
@ -3,7 +3,6 @@ WebRTC Media Agent for Python
|
|||||||
|
|
||||||
This module provides WebRTC signaling server communication and peer connection management.
|
This module provides WebRTC signaling server communication and peer connection management.
|
||||||
Synthetic audio/video track creation is handled by the synthetic_media module.
|
Synthetic audio/video track creation is handled by the synthetic_media module.
|
||||||
Test change to trigger reload - TESTING RELOAD NOW
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
@ -6,7 +6,7 @@ readme = "README.md"
|
|||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aiortc>=1.13.0",
|
"aiortc>=1.13.0",
|
||||||
"numpy>=2.3.2",
|
"numpy<2.3",
|
||||||
"opencv-python>=4.11.0.86",
|
"opencv-python>=4.11.0.86",
|
||||||
"pydantic>=2.11.7",
|
"pydantic>=2.11.7",
|
||||||
"websockets>=15.0.1",
|
"websockets>=15.0.1",
|
||||||
|
@ -13,15 +13,15 @@ audioread==3.0.1
|
|||||||
autograd==1.8.0
|
autograd==1.8.0
|
||||||
av==14.4.0
|
av==14.4.0
|
||||||
brotli==1.1.0
|
brotli==1.1.0
|
||||||
certifi==2022.12.7
|
certifi==2025.8.3
|
||||||
cffi==1.17.1
|
cffi==1.17.1
|
||||||
charset-normalizer==2.1.1
|
charset-normalizer==3.4.3
|
||||||
click==8.2.1
|
click==8.2.1
|
||||||
cma==4.3.0
|
cma==4.3.0
|
||||||
contourpy==1.3.3
|
contourpy==1.3.3
|
||||||
cryptography==45.0.7
|
cryptography==45.0.7
|
||||||
cycler==0.12.1
|
cycler==0.12.1
|
||||||
datasets==2.19.1
|
datasets==4.0.0
|
||||||
decorator==5.2.1
|
decorator==5.2.1
|
||||||
deprecated==1.2.18
|
deprecated==1.2.18
|
||||||
dill==0.3.8
|
dill==0.3.8
|
||||||
@ -31,7 +31,7 @@ ffmpy==0.6.1
|
|||||||
filelock==3.13.1
|
filelock==3.13.1
|
||||||
fonttools==4.59.2
|
fonttools==4.59.2
|
||||||
frozenlist==1.7.0
|
frozenlist==1.7.0
|
||||||
fsspec==2024.2.0
|
fsspec==2024.6.1
|
||||||
google-crc32c==1.7.1
|
google-crc32c==1.7.1
|
||||||
gradio==5.44.1
|
gradio==5.44.1
|
||||||
gradio-client==1.12.1
|
gradio-client==1.12.1
|
||||||
@ -42,7 +42,7 @@ hf-xet==1.1.9
|
|||||||
httpcore==1.0.9
|
httpcore==1.0.9
|
||||||
httpx==0.28.1
|
httpx==0.28.1
|
||||||
huggingface-hub==0.34.4
|
huggingface-hub==0.34.4
|
||||||
idna==3.4
|
idna==3.10
|
||||||
ifaddr==0.2.0
|
ifaddr==0.2.0
|
||||||
jinja2==3.1.4
|
jinja2==3.1.4
|
||||||
jiwer==4.0.0
|
jiwer==4.0.0
|
||||||
@ -70,12 +70,12 @@ numba==0.61.2
|
|||||||
numpy==2.2.6
|
numpy==2.2.6
|
||||||
onnx==1.19.0
|
onnx==1.19.0
|
||||||
opencv-python==4.11.0.86
|
opencv-python==4.11.0.86
|
||||||
openvino==2025.2.0
|
openvino==2025.3.0
|
||||||
openvino-telemetry==2025.2.0
|
openvino-telemetry==2025.2.0
|
||||||
optimum==1.27.0
|
optimum==1.27.0
|
||||||
optimum-intel @ git+https://github.com/huggingface/optimum-intel.git@cd0028599d65e841d6fe16d4d9ccd5528f89f3cb
|
optimum-intel @ git+https://github.com/huggingface/optimum-intel.git@c35534d077dddf9382c6d8699f13412d28b19853
|
||||||
orjson==3.11.3
|
orjson==3.11.3
|
||||||
packaging==24.1
|
packaging==25.0
|
||||||
pandas==2.2.3
|
pandas==2.2.3
|
||||||
pillow==11.3.0
|
pillow==11.3.0
|
||||||
platformdirs==4.4.0
|
platformdirs==4.4.0
|
||||||
@ -84,7 +84,6 @@ propcache==0.3.2
|
|||||||
protobuf==6.32.0
|
protobuf==6.32.0
|
||||||
psutil==7.0.0
|
psutil==7.0.0
|
||||||
pyarrow==21.0.0
|
pyarrow==21.0.0
|
||||||
pyarrow-hotfix==0.7
|
|
||||||
pycparser==2.22
|
pycparser==2.22
|
||||||
pydantic==2.11.7
|
pydantic==2.11.7
|
||||||
pydantic-core==2.33.2
|
pydantic-core==2.33.2
|
||||||
@ -103,7 +102,7 @@ pyyaml==6.0.2
|
|||||||
rapidfuzz==3.14.0
|
rapidfuzz==3.14.0
|
||||||
referencing==0.36.2
|
referencing==0.36.2
|
||||||
regex==2025.9.1
|
regex==2025.9.1
|
||||||
requests==2.28.1
|
requests==2.32.5
|
||||||
rich==14.1.0
|
rich==14.1.0
|
||||||
rpds-py==0.27.1
|
rpds-py==0.27.1
|
||||||
ruff==0.12.11
|
ruff==0.12.11
|
||||||
@ -131,7 +130,7 @@ typer==0.17.3
|
|||||||
typing-extensions==4.15.0
|
typing-extensions==4.15.0
|
||||||
typing-inspection==0.4.1
|
typing-inspection==0.4.1
|
||||||
tzdata==2025.2
|
tzdata==2025.2
|
||||||
urllib3==1.26.13
|
urllib3==2.5.0
|
||||||
uvicorn==0.35.0
|
uvicorn==0.35.0
|
||||||
websockets==15.0.1
|
websockets==15.0.1
|
||||||
wrapt==1.17.3
|
wrapt==1.17.3
|
||||||
|
@ -13,7 +13,8 @@ import time
|
|||||||
import random
|
import random
|
||||||
from av.audio.frame import AudioFrame
|
from av.audio.frame import AudioFrame
|
||||||
from asyncio import Queue, create_task, sleep
|
from asyncio import Queue, create_task, sleep
|
||||||
from typing import TypedDict, TYPE_CHECKING
|
from typing import TypedDict, TYPE_CHECKING, Tuple, List, Optional, Any
|
||||||
|
import numpy.typing as npt
|
||||||
from aiortc import MediaStreamTrack
|
from aiortc import MediaStreamTrack
|
||||||
from av import VideoFrame
|
from av import VideoFrame
|
||||||
from logger import logger
|
from logger import logger
|
||||||
@ -42,13 +43,7 @@ class BounceEvent(TypedDict):
|
|||||||
|
|
||||||
|
|
||||||
class AnimatedVideoTrack(MediaStreamTrack):
|
class AnimatedVideoTrack(MediaStreamTrack):
|
||||||
"""
|
"""Animated synthetic video track (fixed, properly-indented implementation)."""
|
||||||
Synthetic video track that generates animated content with a bouncing ball.
|
|
||||||
|
|
||||||
Can also composite remote video tracks with edge detection overlay.
|
|
||||||
Remote video tracks are processed through Canny edge detection and blended
|
|
||||||
with the synthetic ball animation.
|
|
||||||
"""
|
|
||||||
|
|
||||||
kind = "video"
|
kind = "video"
|
||||||
|
|
||||||
@ -58,117 +53,98 @@ class AnimatedVideoTrack(MediaStreamTrack):
|
|||||||
width: int = 320,
|
width: int = 320,
|
||||||
height: int = 240,
|
height: int = 240,
|
||||||
name: str = "",
|
name: str = "",
|
||||||
audio_track: "SyntheticAudioTrack | None" = None,
|
audio_track: Optional["SyntheticAudioTrack"] = None,
|
||||||
):
|
) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
self.name = name
|
self.name = name
|
||||||
self.clock = clock
|
self.clock = clock
|
||||||
self.fps = 15
|
|
||||||
self._next_frame_index = 0
|
self._next_frame_index = 0
|
||||||
|
|
||||||
self.audio_track = audio_track # Reference to the audio track
|
self.audio_track = audio_track
|
||||||
self.remote_video_tracks: list[
|
self.remote_video_tracks: List[MediaStreamTrack] = []
|
||||||
MediaStreamTrack
|
|
||||||
] = [] # Store remote video tracks
|
|
||||||
|
|
||||||
# Generate color from name hash (similar to JavaScript nameToColor)
|
self.ball_color = self._name_to_color(name) if name else (0, 255, 136)
|
||||||
self.ball_color = (
|
|
||||||
self._name_to_color(name) if name else (0, 255, 136)
|
|
||||||
) # Default green
|
|
||||||
|
|
||||||
# Ball properties
|
|
||||||
ball_radius = min(width, height) * 0.06
|
ball_radius = min(width, height) * 0.06
|
||||||
self.ball = {
|
self.ball = {
|
||||||
"x": random.uniform(ball_radius, width - ball_radius),
|
"x": random.uniform(ball_radius, width - ball_radius),
|
||||||
"y": random.uniform(ball_radius, height - ball_radius),
|
"y": random.uniform(ball_radius, height - ball_radius),
|
||||||
"radius": ball_radius,
|
"radius": ball_radius,
|
||||||
"speed_mps": 0.5, # Speed in meters per second (frame width = 1 meter)
|
"speed_mps": 0.5,
|
||||||
"direction_x": random.uniform(
|
"direction_x": random.uniform(-1.0, 1.0),
|
||||||
-1.0, 1.0
|
"direction_y": random.uniform(-1.0, 1.0),
|
||||||
), # Random direction x component (-1 to 1)
|
|
||||||
"direction_y": random.uniform(
|
|
||||||
-1.0, 1.0
|
|
||||||
), # Random direction y component (-1 to 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.frame_count = 0
|
self.frame_count = 0
|
||||||
self._start_time = time.time()
|
self._start_time = time.time()
|
||||||
self._last_frame_time = time.time()
|
self._last_frame_time = time.time()
|
||||||
self.fps = 15 # Target frames per second
|
self.fps = 15
|
||||||
self._remote_latest = {} # track -> np.ndarray
|
|
||||||
self._remote_tasks: list[
|
|
||||||
tuple[MediaStreamTrack, object, Queue[np.ndarray]]
|
|
||||||
] = []
|
|
||||||
|
|
||||||
def set_ball_speed(self, speed_mps: float):
|
self._remote_latest: dict[MediaStreamTrack, npt.NDArray[Any]] = {}
|
||||||
"""Set the ball speed in meters per second"""
|
self._remote_tasks: List[Tuple[MediaStreamTrack, object, Queue[npt.NDArray[Any]]]] = []
|
||||||
|
|
||||||
|
def set_ball_speed(self, speed_mps: float) -> None:
|
||||||
self.ball["speed_mps"] = speed_mps
|
self.ball["speed_mps"] = speed_mps
|
||||||
|
|
||||||
def add_remote_video_track(self, track: MediaStreamTrack):
|
def add_remote_video_track(self, track: MediaStreamTrack) -> None:
|
||||||
"""Add a remote video track to be composited with edge detection"""
|
if track.kind != "video":
|
||||||
if track.kind == "video":
|
return
|
||||||
self.remote_video_tracks.append(track)
|
self.remote_video_tracks.append(track)
|
||||||
logger.info(f"Added remote video track: {track}")
|
logger.info("Added remote video track: %s", track)
|
||||||
q: Queue[np.ndarray] = Queue(maxsize=1)
|
q: Queue[npt.NDArray[Any]] = Queue(maxsize=1)
|
||||||
|
|
||||||
async def pump():
|
async def pump() -> None:
|
||||||
while True:
|
while True:
|
||||||
frame = await track.recv()
|
frame = await track.recv()
|
||||||
if isinstance(frame, VideoFrame):
|
if isinstance(frame, VideoFrame):
|
||||||
img: np.ndarray = frame.to_ndarray(format="bgr24")
|
img = frame.to_ndarray(format="bgr24")
|
||||||
if q.full():
|
if q.full():
|
||||||
|
try:
|
||||||
_ = q.get_nowait()
|
_ = q.get_nowait()
|
||||||
await q.put(img)
|
except Exception:
|
||||||
|
pass
|
||||||
|
await q.put(img)
|
||||||
|
|
||||||
t = create_task(pump())
|
t = create_task(pump())
|
||||||
self._remote_tasks.append((track, t, q))
|
self._remote_tasks.append((track, t, q))
|
||||||
|
|
||||||
def remove_remote_video_track(self, track: MediaStreamTrack):
|
def remove_remote_video_track(self, track: MediaStreamTrack) -> None:
|
||||||
"""Remove a remote video track"""
|
|
||||||
if track in self.remote_video_tracks:
|
if track in self.remote_video_tracks:
|
||||||
self.remote_video_tracks.remove(track)
|
self.remote_video_tracks.remove(track)
|
||||||
logger.info(f"Removed remote video track: {track}")
|
logger.info("Removed remote video track: %s", track)
|
||||||
|
|
||||||
def _calculate_velocity_components(self, dt: float) -> tuple[float, float]:
|
def _calculate_velocity_components(self, dt: float) -> Tuple[float, float]:
|
||||||
dir_x, dir_y = self.ball["direction_x"], self.ball["direction_y"]
|
dir_x = float(self.ball["direction_x"])
|
||||||
mag = np.hypot(dir_x, dir_y)
|
dir_y = float(self.ball["direction_y"])
|
||||||
|
mag = math.hypot(dir_x, dir_y)
|
||||||
if mag == 0:
|
if mag == 0:
|
||||||
dir_x_norm, dir_y_norm = 1.0, 0.0
|
dir_x_norm, dir_y_norm = 1.0, 0.0
|
||||||
else:
|
else:
|
||||||
dir_x_norm, dir_y_norm = dir_x / mag, dir_y / mag
|
dir_x_norm, dir_y_norm = dir_x / mag, dir_y / mag
|
||||||
pixels_per_second = self.width * self.ball["speed_mps"]
|
pixels_per_second = self.width * float(self.ball["speed_mps"])
|
||||||
pixels_this_frame = pixels_per_second * dt
|
pixels_this_frame = pixels_per_second * dt
|
||||||
return pixels_this_frame * dir_x_norm, pixels_this_frame * dir_y_norm
|
return pixels_this_frame * dir_x_norm, pixels_this_frame * dir_y_norm
|
||||||
|
|
||||||
async def next_timestamp(self):
|
async def next_timestamp(self) -> Tuple[int, float]:
|
||||||
"""Returns (pts, time_base) for 15 FPS video"""
|
pts = int(self.frame_count * (1 / self.fps) * 90000)
|
||||||
pts = int(self.frame_count * (1 / 15) * 90000)
|
|
||||||
time_base = 1 / 90000
|
time_base = 1 / 90000
|
||||||
return pts, time_base
|
return pts, time_base
|
||||||
|
|
||||||
def _name_to_color(self, name: str) -> tuple[int, int, int]:
|
def _name_to_color(self, name: str) -> Tuple[int, int, int]:
|
||||||
"""Convert name to HSL color, then to RGB tuple"""
|
|
||||||
# Simple hash function (djb2)
|
|
||||||
hash_value = 5381
|
hash_value = 5381
|
||||||
for char in name:
|
for ch in name:
|
||||||
hash_value = ((hash_value << 5) + hash_value + ord(char)) & 0xFFFFFFFF
|
hash_value = ((hash_value << 5) + hash_value + ord(ch)) & 0xFFFFFFFF
|
||||||
|
|
||||||
# Generate HSL color from hash
|
|
||||||
hue = abs(hash_value) % 360
|
hue = abs(hash_value) % 360
|
||||||
sat = 60 + (abs(hash_value) % 30) # 60-89%
|
sat = 60 + (abs(hash_value) % 30)
|
||||||
light = 45 + (abs(hash_value) % 30) # 45-74%
|
light = 45 + (abs(hash_value) % 30)
|
||||||
|
|
||||||
# Convert HSL to RGB
|
|
||||||
h = hue / 360.0
|
h = hue / 360.0
|
||||||
s = sat / 100.0
|
s = sat / 100.0
|
||||||
lightness = light / 100.0
|
lightness = light / 100.0
|
||||||
|
|
||||||
c = (1 - abs(2 * lightness - 1)) * s
|
c = (1 - abs(2 * lightness - 1)) * s
|
||||||
x = c * (1 - abs((h * 6) % 2 - 1))
|
x = c * (1 - abs((h * 6) % 2 - 1))
|
||||||
m = lightness - c / 2
|
m = lightness - c / 2
|
||||||
|
|
||||||
if h < 1 / 6:
|
if h < 1 / 6:
|
||||||
r, g, b = c, x, 0
|
r, g, b = c, x, 0
|
||||||
elif h < 2 / 6:
|
elif h < 2 / 6:
|
||||||
@ -181,54 +157,42 @@ class AnimatedVideoTrack(MediaStreamTrack):
|
|||||||
r, g, b = x, 0, c
|
r, g, b = x, 0, c
|
||||||
else:
|
else:
|
||||||
r, g, b = c, 0, x
|
r, g, b = c, 0, x
|
||||||
|
return int((b + m) * 255), int((g + m) * 255), int((r + m) * 255)
|
||||||
|
|
||||||
return (
|
async def recv(self) -> VideoFrame:
|
||||||
int((b + m) * 255),
|
|
||||||
int((g + m) * 255),
|
|
||||||
int((r + m) * 255),
|
|
||||||
) # BGR for OpenCV
|
|
||||||
|
|
||||||
async def recv(self):
|
|
||||||
"""Generate video frames at 15 FPS"""
|
|
||||||
pts, time_base = await self.next_timestamp()
|
pts, time_base = await self.next_timestamp()
|
||||||
|
|
||||||
# Target timestamp for this frame (seconds since t0)
|
# schedule frame according to clock
|
||||||
target_t = self._next_frame_index / self.fps
|
target_t = self._next_frame_index / self.fps
|
||||||
now = self.clock.now()
|
now = self.clock.now()
|
||||||
if target_t > now:
|
if target_t > now:
|
||||||
await sleep(target_t - now)
|
await sleep(target_t - now)
|
||||||
|
|
||||||
# Use constant dt tied to fps (prevents physics jitter)
|
|
||||||
dt = 1.0 / self.fps
|
dt = 1.0 / self.fps
|
||||||
dx, dy = self._calculate_velocity_components(dt)
|
dx, dy = self._calculate_velocity_components(dt)
|
||||||
|
|
||||||
# PTS derived from frame index, not wall clock
|
|
||||||
pts = int(self._next_frame_index * (90000 / self.fps))
|
pts = int(self._next_frame_index * (90000 / self.fps))
|
||||||
time_base = 1 / 90000
|
time_base = 1 / 90000
|
||||||
|
|
||||||
self._next_frame_index += 1
|
self._next_frame_index += 1
|
||||||
|
|
||||||
# Create black background
|
frame_array: npt.NDArray[np.uint8] = np.zeros((self.height, self.width, 3), dtype=np.uint8)
|
||||||
frame_array = np.zeros((self.height, self.width, 3), dtype=np.uint8)
|
|
||||||
|
|
||||||
# Process remote video tracks with edge detection
|
# Blend in edge-detected remote frames if available
|
||||||
for _track, _task, q in self._remote_tasks:
|
for _track, _task, q in self._remote_tasks:
|
||||||
try:
|
try:
|
||||||
img: np.ndarray = q.get_nowait()
|
img = q.get_nowait()
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
edges = cv2.Canny(img, 100, 200)
|
edges = cv2.Canny(img, 100, 200)
|
||||||
img_edges = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)
|
img_edges = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)
|
||||||
if img_edges.shape[:2] != (self.height, self.width):
|
if img_edges.shape[:2] != (self.height, self.width):
|
||||||
img_edges = cv2.resize(img_edges, (self.width, self.height))
|
img_edges = cv2.resize(img_edges, (self.width, self.height))
|
||||||
frame_array = cv2.addWeighted(frame_array, 0.7, img_edges, 0.3, 0.0)
|
frame_array = cv2.addWeighted(frame_array, 0.7, img_edges, 0.3, 0.0).astype(np.uint8)
|
||||||
|
|
||||||
# Update ball position
|
# Update ball position and handle bouncing
|
||||||
ball = self.ball
|
ball = self.ball
|
||||||
ball["x"] += dx
|
ball["x"] += dx
|
||||||
ball["y"] += dy
|
ball["y"] += dy
|
||||||
|
|
||||||
# Bounce off walls and trigger audio events
|
|
||||||
bounce_occurred = False
|
bounce_occurred = False
|
||||||
if ball["x"] + ball["radius"] >= self.width or ball["x"] - ball["radius"] <= 0:
|
if ball["x"] + ball["radius"] >= self.width or ball["x"] - ball["radius"] <= 0:
|
||||||
ball["direction_x"] = -ball["direction_x"]
|
ball["direction_x"] = -ball["direction_x"]
|
||||||
@ -237,48 +201,21 @@ class AnimatedVideoTrack(MediaStreamTrack):
|
|||||||
ball["direction_y"] = -ball["direction_y"]
|
ball["direction_y"] = -ball["direction_y"]
|
||||||
bounce_occurred = True
|
bounce_occurred = True
|
||||||
|
|
||||||
# Trigger bounce sound if a bounce occurred
|
if bounce_occurred and self.audio_track is not None:
|
||||||
if bounce_occurred and self.audio_track:
|
|
||||||
logger.info("Video: Bounce detected, triggering audio event")
|
logger.info("Video: Bounce detected, triggering audio event")
|
||||||
self.audio_track.add_bounce_event_at(self.clock.now())
|
self.audio_track.add_bounce_event_at(self.clock.now())
|
||||||
|
|
||||||
# Keep ball in bounds
|
|
||||||
ball["x"] = max(ball["radius"], min(self.width - ball["radius"], ball["x"]))
|
ball["x"] = max(ball["radius"], min(self.width - ball["radius"], ball["x"]))
|
||||||
ball["y"] = max(ball["radius"], min(self.height - ball["radius"], ball["y"]))
|
ball["y"] = max(ball["radius"], min(self.height - ball["radius"], ball["y"]))
|
||||||
|
|
||||||
# Draw ball
|
cv2.circle(frame_array, (int(ball["x"]), int(ball["y"])), int(ball["radius"]), self.ball_color, -1)
|
||||||
cv2.circle(
|
|
||||||
frame_array,
|
|
||||||
(int(ball["x"]), int(ball["y"])),
|
|
||||||
int(ball["radius"]),
|
|
||||||
self.ball_color,
|
|
||||||
-1,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Add frame counter and speed text
|
|
||||||
frame_text = f"Frame: {int(time.time() * 1000) % 10000}"
|
frame_text = f"Frame: {int(time.time() * 1000) % 10000}"
|
||||||
speed_text = f"Speed: {ball['speed_mps']:.2f} m/s"
|
speed_text = f"Speed: {ball['speed_mps']:.2f} m/s"
|
||||||
cv2.putText(
|
cv2.putText(frame_array, frame_text, (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
|
||||||
frame_array,
|
cv2.putText(frame_array, speed_text, (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
|
||||||
frame_text,
|
|
||||||
(10, 20),
|
|
||||||
cv2.FONT_HERSHEY_SIMPLEX,
|
|
||||||
0.5,
|
|
||||||
(255, 255, 255),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
cv2.putText(
|
|
||||||
frame_array,
|
|
||||||
speed_text,
|
|
||||||
(10, 40),
|
|
||||||
cv2.FONT_HERSHEY_SIMPLEX,
|
|
||||||
0.5,
|
|
||||||
(255, 255, 255),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Convert to VideoFrame
|
frame = VideoFrame.from_ndarray(frame_array, format="bgr24")
|
||||||
frame = VideoFrame.from_ndarray(frame_array.astype(np.uint8), format="bgr24")
|
|
||||||
frame.pts = pts
|
frame.pts = pts
|
||||||
frame.time_base = fractions.Fraction(time_base).limit_denominator(1000000)
|
frame.time_base = fractions.Fraction(time_base).limit_denominator(1000000)
|
||||||
|
|
||||||
|
91
voicebot/uv.lock
generated
91
voicebot/uv.lock
generated
@ -22,7 +22,7 @@ dependencies = [
|
|||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "aiortc", specifier = ">=1.13.0" },
|
{ name = "aiortc", specifier = ">=1.13.0" },
|
||||||
{ name = "numpy", specifier = ">=2.3.2" },
|
{ name = "numpy", specifier = "<2.3" },
|
||||||
{ name = "opencv-python", specifier = ">=4.11.0.86" },
|
{ name = "opencv-python", specifier = ">=4.11.0.86" },
|
||||||
{ name = "pydantic", specifier = ">=2.11.7" },
|
{ name = "pydantic", specifier = ">=2.11.7" },
|
||||||
{ name = "websockets", specifier = ">=15.0.1" },
|
{ name = "websockets", specifier = ">=15.0.1" },
|
||||||
@ -203,65 +203,40 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "numpy"
|
name = "numpy"
|
||||||
version = "2.3.2"
|
version = "2.2.6"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/37/7d/3fec4199c5ffb892bed55cff901e4f39a58c81df9c44c280499e92cad264/numpy-2.3.2.tar.gz", hash = "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48", size = 20489306, upload-time = "2025-07-24T21:32:07.553Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/00/6d/745dd1c1c5c284d17725e5c802ca4d45cfc6803519d777f087b71c9f4069/numpy-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bc3186bea41fae9d8e90c2b4fb5f0a1f5a690682da79b92574d63f56b529080b", size = 20956420, upload-time = "2025-07-24T20:28:18.002Z" },
|
{ url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff", size = 20875348, upload-time = "2025-05-17T21:34:39.648Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/bc/96/e7b533ea5740641dd62b07a790af5d9d8fec36000b8e2d0472bd7574105f/numpy-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f4f0215edb189048a3c03bd5b19345bdfa7b45a7a6f72ae5945d2a28272727f", size = 14184660, upload-time = "2025-07-24T20:28:39.522Z" },
|
{ url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c", size = 14119362, upload-time = "2025-05-17T21:35:01.241Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/2b/53/102c6122db45a62aa20d1b18c9986f67e6b97e0d6fbc1ae13e3e4c84430c/numpy-2.3.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b1224a734cd509f70816455c3cffe13a4f599b1bf7130f913ba0e2c0b2006c0", size = 5113382, upload-time = "2025-07-24T20:28:48.544Z" },
|
{ url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3", size = 5084103, upload-time = "2025-05-17T21:35:10.622Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/2b/21/376257efcbf63e624250717e82b4fae93d60178f09eb03ed766dbb48ec9c/numpy-2.3.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3dcf02866b977a38ba3ec10215220609ab9667378a9e2150615673f3ffd6c73b", size = 6647258, upload-time = "2025-07-24T20:28:59.104Z" },
|
{ url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282", size = 6625382, upload-time = "2025-05-17T21:35:21.414Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/91/ba/f4ebf257f08affa464fe6036e13f2bf9d4642a40228781dc1235da81be9f/numpy-2.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:572d5512df5470f50ada8d1972c5f1082d9a0b7aa5944db8084077570cf98370", size = 14281409, upload-time = "2025-07-24T20:40:30.298Z" },
|
{ url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87", size = 14018462, upload-time = "2025-05-17T21:35:42.174Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/59/ef/f96536f1df42c668cbacb727a8c6da7afc9c05ece6d558927fb1722693e1/numpy-2.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73", size = 16641317, upload-time = "2025-07-24T20:40:56.625Z" },
|
{ url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249", size = 16527618, upload-time = "2025-05-17T21:36:06.711Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f6/a7/af813a7b4f9a42f498dde8a4c6fcbff8100eed00182cc91dbaf095645f38/numpy-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:103ea7063fa624af04a791c39f97070bf93b96d7af7eb23530cd087dc8dbe9dc", size = 16056262, upload-time = "2025-07-24T20:41:20.797Z" },
|
{ url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49", size = 15505511, upload-time = "2025-05-17T21:36:29.965Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8b/5d/41c4ef8404caaa7f05ed1cfb06afe16a25895260eacbd29b4d84dff2920b/numpy-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc927d7f289d14f5e037be917539620603294454130b6de200091e23d27dc9be", size = 18579342, upload-time = "2025-07-24T20:41:50.753Z" },
|
{ url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/a1/4f/9950e44c5a11636f4a3af6e825ec23003475cc9a466edb7a759ed3ea63bd/numpy-2.3.2-cp312-cp312-win32.whl", hash = "sha256:d95f59afe7f808c103be692175008bab926b59309ade3e6d25009e9a171f7036", size = 6320610, upload-time = "2025-07-24T20:42:01.551Z" },
|
{ url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7c/2f/244643a5ce54a94f0a9a2ab578189c061e4a87c002e037b0829dd77293b6/numpy-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:9e196ade2400c0c737d93465327d1ae7c06c7cb8a1756121ebf54b06ca183c7f", size = 12786292, upload-time = "2025-07-24T20:42:20.738Z" },
|
{ url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/54/cd/7b5f49d5d78db7badab22d8323c1b6ae458fbf86c4fdfa194ab3cd4eb39b/numpy-2.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07", size = 10194071, upload-time = "2025-07-24T20:42:36.657Z" },
|
{ url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/1c/c0/c6bb172c916b00700ed3bf71cb56175fd1f7dbecebf8353545d0b5519f6c/numpy-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c8d9727f5316a256425892b043736d63e89ed15bbfe6556c5ff4d9d4448ff3b3", size = 20949074, upload-time = "2025-07-24T20:43:07.813Z" },
|
{ url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/20/4e/c116466d22acaf4573e58421c956c6076dc526e24a6be0903219775d862e/numpy-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:efc81393f25f14d11c9d161e46e6ee348637c0a1e8a54bf9dedc472a3fae993b", size = 14177311, upload-time = "2025-07-24T20:43:29.335Z" },
|
{ url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/78/45/d4698c182895af189c463fc91d70805d455a227261d950e4e0f1310c2550/numpy-2.3.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dd937f088a2df683cbb79dda9a772b62a3e5a8a7e76690612c2737f38c6ef1b6", size = 5106022, upload-time = "2025-07-24T20:43:37.999Z" },
|
{ url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9f/76/3e6880fef4420179309dba72a8c11f6166c431cf6dee54c577af8906f914/numpy-2.3.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:11e58218c0c46c80509186e460d79fbdc9ca1eb8d8aee39d8f2dc768eb781089", size = 6640135, upload-time = "2025-07-24T20:43:49.28Z" },
|
{ url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/34/fa/87ff7f25b3c4ce9085a62554460b7db686fef1e0207e8977795c7b7d7ba1/numpy-2.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5ad4ebcb683a1f99f4f392cc522ee20a18b2bb12a2c1c42c3d48d5a1adc9d3d2", size = 14278147, upload-time = "2025-07-24T20:44:10.328Z" },
|
{ url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/1d/0f/571b2c7a3833ae419fe69ff7b479a78d313581785203cc70a8db90121b9a/numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f", size = 16635989, upload-time = "2025-07-24T20:44:34.88Z" },
|
{ url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/24/5a/84ae8dca9c9a4c592fe11340b36a86ffa9fd3e40513198daf8a97839345c/numpy-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:66459dccc65d8ec98cc7df61307b64bf9e08101f9598755d42d8ae65d9a7a6ee", size = 16053052, upload-time = "2025-07-24T20:44:58.872Z" },
|
{ url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/57/7c/e5725d99a9133b9813fcf148d3f858df98511686e853169dbaf63aec6097/numpy-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7af9ed2aa9ec5950daf05bb11abc4076a108bd3c7db9aa7251d5f107079b6a6", size = 18577955, upload-time = "2025-07-24T20:45:26.714Z" },
|
{ url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ae/11/7c546fcf42145f29b71e4d6f429e96d8d68e5a7ba1830b2e68d7418f0bbd/numpy-2.3.2-cp313-cp313-win32.whl", hash = "sha256:906a30249315f9c8e17b085cc5f87d3f369b35fedd0051d4a84686967bdbbd0b", size = 6311843, upload-time = "2025-07-24T20:49:24.444Z" },
|
{ url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/aa/6f/a428fd1cb7ed39b4280d057720fed5121b0d7754fd2a9768640160f5517b/numpy-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:c63d95dc9d67b676e9108fe0d2182987ccb0f11933c1e8959f42fa0da8d4fa56", size = 12782876, upload-time = "2025-07-24T20:49:43.227Z" },
|
{ url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/65/85/4ea455c9040a12595fb6c43f2c217257c7b52dd0ba332c6a6c1d28b289fe/numpy-2.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:b05a89f2fb84d21235f93de47129dd4f11c16f64c87c33f5e284e6a3a54e43f2", size = 10192786, upload-time = "2025-07-24T20:49:59.443Z" },
|
{ url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/80/23/8278f40282d10c3f258ec3ff1b103d4994bcad78b0cba9208317f6bb73da/numpy-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e6ecfeddfa83b02318f4d84acf15fbdbf9ded18e46989a15a8b6995dfbf85ab", size = 21047395, upload-time = "2025-07-24T20:45:58.821Z" },
|
{ url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/1f/2d/624f2ce4a5df52628b4ccd16a4f9437b37c35f4f8a50d00e962aae6efd7a/numpy-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:508b0eada3eded10a3b55725b40806a4b855961040180028f52580c4729916a2", size = 14300374, upload-time = "2025-07-24T20:46:20.207Z" },
|
{ url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f6/62/ff1e512cdbb829b80a6bd08318a58698867bca0ca2499d101b4af063ee97/numpy-2.3.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:754d6755d9a7588bdc6ac47dc4ee97867271b17cee39cb87aef079574366db0a", size = 5228864, upload-time = "2025-07-24T20:46:30.58Z" },
|
{ url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7d/8e/74bc18078fff03192d4032cfa99d5a5ca937807136d6f5790ce07ca53515/numpy-2.3.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f66e7d2b2d7712410d3bc5684149040ef5f19856f20277cd17ea83e5006286", size = 6737533, upload-time = "2025-07-24T20:46:46.111Z" },
|
{ url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/19/ea/0731efe2c9073ccca5698ef6a8c3667c4cf4eea53fcdcd0b50140aba03bc/numpy-2.3.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de6ea4e5a65d5a90c7d286ddff2b87f3f4ad61faa3db8dabe936b34c2275b6f8", size = 14352007, upload-time = "2025-07-24T20:47:07.1Z" },
|
{ url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/cf/90/36be0865f16dfed20f4bc7f75235b963d5939707d4b591f086777412ff7b/numpy-2.3.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3ef07ec8cbc8fc9e369c8dcd52019510c12da4de81367d8b20bc692aa07573a", size = 16701914, upload-time = "2025-07-24T20:47:32.459Z" },
|
{ url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/94/30/06cd055e24cb6c38e5989a9e747042b4e723535758e6153f11afea88c01b/numpy-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:27c9f90e7481275c7800dc9c24b7cc40ace3fdb970ae4d21eaff983a32f70c91", size = 16132708, upload-time = "2025-07-24T20:47:58.129Z" },
|
{ url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9a/14/ecede608ea73e58267fd7cb78f42341b3b37ba576e778a1a06baffbe585c/numpy-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:07b62978075b67eee4065b166d000d457c82a1efe726cce608b9db9dd66a73a5", size = 18651678, upload-time = "2025-07-24T20:48:25.402Z" },
|
{ url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/40/f3/2fe6066b8d07c3685509bc24d56386534c008b462a488b7f503ba82b8923/numpy-2.3.2-cp313-cp313t-win32.whl", hash = "sha256:c771cfac34a4f2c0de8e8c97312d07d64fd8f8ed45bc9f5726a7e947270152b5", size = 6441832, upload-time = "2025-07-24T20:48:37.181Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0b/ba/0937d66d05204d8f28630c9c60bc3eda68824abde4cf756c4d6aad03b0c6/numpy-2.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:72dbebb2dcc8305c431b2836bcc66af967df91be793d63a24e3d9b741374c450", size = 12927049, upload-time = "2025-07-24T20:48:56.24Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e9/ed/13542dd59c104d5e654dfa2ac282c199ba64846a74c2c4bcdbc3a0f75df1/numpy-2.3.2-cp313-cp313t-win_arm64.whl", hash = "sha256:72c6df2267e926a6d5286b0a6d556ebe49eae261062059317837fda12ddf0c1a", size = 10262935, upload-time = "2025-07-24T20:49:13.136Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c9/7c/7659048aaf498f7611b783e000c7268fcc4dcf0ce21cd10aad7b2e8f9591/numpy-2.3.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:448a66d052d0cf14ce9865d159bfc403282c9bc7bb2a31b03cc18b651eca8b1a", size = 20950906, upload-time = "2025-07-24T20:50:30.346Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/80/db/984bea9d4ddf7112a04cfdfb22b1050af5757864cfffe8e09e44b7f11a10/numpy-2.3.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:546aaf78e81b4081b2eba1d105c3b34064783027a06b3ab20b6eba21fb64132b", size = 14185607, upload-time = "2025-07-24T20:50:51.923Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e4/76/b3d6f414f4eca568f469ac112a3b510938d892bc5a6c190cb883af080b77/numpy-2.3.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:87c930d52f45df092f7578889711a0768094debf73cfcde105e2d66954358125", size = 5114110, upload-time = "2025-07-24T20:51:01.041Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9e/d2/6f5e6826abd6bca52392ed88fe44a4b52aacb60567ac3bc86c67834c3a56/numpy-2.3.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:8dc082ea901a62edb8f59713c6a7e28a85daddcb67454c839de57656478f5b19", size = 6642050, upload-time = "2025-07-24T20:51:11.64Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c4/43/f12b2ade99199e39c73ad182f103f9d9791f48d885c600c8e05927865baf/numpy-2.3.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af58de8745f7fa9ca1c0c7c943616c6fe28e75d0c81f5c295810e3c83b5be92f", size = 14296292, upload-time = "2025-07-24T20:51:33.488Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/5d/f9/77c07d94bf110a916b17210fac38680ed8734c236bfed9982fd8524a7b47/numpy-2.3.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed5527c4cf10f16c6d0b6bee1f89958bccb0ad2522c8cadc2efd318bcd545f5", size = 16638913, upload-time = "2025-07-24T20:51:58.517Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9b/d1/9d9f2c8ea399cc05cfff8a7437453bd4e7d894373a93cdc46361bbb49a7d/numpy-2.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:095737ed986e00393ec18ec0b21b47c22889ae4b0cd2d5e88342e08b01141f58", size = 16071180, upload-time = "2025-07-24T20:52:22.827Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4c/41/82e2c68aff2a0c9bf315e47d61951099fed65d8cb2c8d9dc388cb87e947e/numpy-2.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5e40e80299607f597e1a8a247ff8d71d79c5b52baa11cc1cce30aa92d2da6e0", size = 18576809, upload-time = "2025-07-24T20:52:51.015Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/14/14/4b4fd3efb0837ed252d0f583c5c35a75121038a8c4e065f2c259be06d2d8/numpy-2.3.2-cp314-cp314-win32.whl", hash = "sha256:7d6e390423cc1f76e1b8108c9b6889d20a7a1f59d9a60cac4a050fa734d6c1e2", size = 6366410, upload-time = "2025-07-24T20:56:44.949Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/11/9e/b4c24a6b8467b61aced5c8dc7dcfce23621baa2e17f661edb2444a418040/numpy-2.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:b9d0878b21e3918d76d2209c924ebb272340da1fb51abc00f986c258cd5e957b", size = 12918821, upload-time = "2025-07-24T20:57:06.479Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0e/0f/0dc44007c70b1007c1cef86b06986a3812dd7106d8f946c09cfa75782556/numpy-2.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:2738534837c6a1d0c39340a190177d7d66fdf432894f469728da901f8f6dc910", size = 10477303, upload-time = "2025-07-24T20:57:22.879Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8b/3e/075752b79140b78ddfc9c0a1634d234cfdbc6f9bbbfa6b7504e445ad7d19/numpy-2.3.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:4d002ecf7c9b53240be3bb69d80f86ddbd34078bae04d87be81c1f58466f264e", size = 21047524, upload-time = "2025-07-24T20:53:22.086Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fe/6d/60e8247564a72426570d0e0ea1151b95ce5bd2f1597bb878a18d32aec855/numpy-2.3.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:293b2192c6bcce487dbc6326de5853787f870aeb6c43f8f9c6496db5b1781e45", size = 14300519, upload-time = "2025-07-24T20:53:44.053Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4d/73/d8326c442cd428d47a067070c3ac6cc3b651a6e53613a1668342a12d4479/numpy-2.3.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:0a4f2021a6da53a0d580d6ef5db29947025ae8b35b3250141805ea9a32bbe86b", size = 5228972, upload-time = "2025-07-24T20:53:53.81Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/34/2e/e71b2d6dad075271e7079db776196829019b90ce3ece5c69639e4f6fdc44/numpy-2.3.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9c144440db4bf3bb6372d2c3e49834cc0ff7bb4c24975ab33e01199e645416f2", size = 6737439, upload-time = "2025-07-24T20:54:04.742Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/15/b0/d004bcd56c2c5e0500ffc65385eb6d569ffd3363cb5e593ae742749b2daa/numpy-2.3.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f92d6c2a8535dc4fe4419562294ff957f83a16ebdec66df0805e473ffaad8bd0", size = 14352479, upload-time = "2025-07-24T20:54:25.819Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/11/e3/285142fcff8721e0c99b51686426165059874c150ea9ab898e12a492e291/numpy-2.3.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cefc2219baa48e468e3db7e706305fcd0c095534a192a08f31e98d83a7d45fb0", size = 16702805, upload-time = "2025-07-24T20:54:50.814Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/33/c3/33b56b0e47e604af2c7cd065edca892d180f5899599b76830652875249a3/numpy-2.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:76c3e9501ceb50b2ff3824c3589d5d1ab4ac857b0ee3f8f49629d0de55ecf7c2", size = 16133830, upload-time = "2025-07-24T20:55:17.306Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/6e/ae/7b1476a1f4d6a48bc669b8deb09939c56dd2a439db1ab03017844374fb67/numpy-2.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:122bf5ed9a0221b3419672493878ba4967121514b1d7d4656a7580cd11dddcbf", size = 18652665, upload-time = "2025-07-24T20:55:46.665Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/14/ba/5b5c9978c4bb161034148ade2de9db44ec316fab89ce8c400db0e0c81f86/numpy-2.3.2-cp314-cp314t-win32.whl", hash = "sha256:6f1ae3dcb840edccc45af496f312528c15b1f79ac318169d094e85e4bb35fdf1", size = 6514777, upload-time = "2025-07-24T20:55:57.66Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/eb/46/3dbaf0ae7c17cdc46b9f662c56da2054887b8d9e737c1476f335c83d33db/numpy-2.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:087ffc25890d89a43536f75c5fe8770922008758e8eeeef61733957041ed2f9b", size = 13111856, upload-time = "2025-07-24T20:56:17.318Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c1/9e/1652778bce745a67b5fe05adde60ed362d38eb17d919a540e813d30f6874/numpy-2.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631", size = 10544226, upload-time = "2025-07-24T20:56:34.509Z" },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
import librosa
|
import librosa
|
||||||
import numpy as np
|
|
||||||
from logger import logger
|
from logger import logger
|
||||||
from transformers import AutoProcessor, AutoModelForSpeechSeq2Seq
|
from transformers import AutoProcessor, AutoModelForSpeechSeq2Seq
|
||||||
|
|
||||||
@ -37,7 +36,7 @@ pt_model: Any = AutoModelForSpeechSeq2Seq.from_pretrained(pretrained_model_name_
|
|||||||
pt_model.eval() # type: ignore
|
pt_model.eval() # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def extract_input_features(audio_array: np.ndarray, sampling_rate: int):
|
def extract_input_features(audio_array: Any, sampling_rate: int) -> Any:
|
||||||
"""Extract input features from audio array and sampling rate."""
|
"""Extract input features from audio array and sampling rate."""
|
||||||
input_features = processor(
|
input_features = processor(
|
||||||
audio_array,
|
audio_array,
|
||||||
@ -47,13 +46,22 @@ def extract_input_features(audio_array: np.ndarray, sampling_rate: int):
|
|||||||
return input_features
|
return input_features
|
||||||
|
|
||||||
|
|
||||||
def load_audio_file(file_path: str) -> tuple[np.ndarray, int]:
|
def load_audio_file(file_path: str) -> tuple[Any, int]:
|
||||||
"""Load audio file from disk and return audio array and sampling rate."""
|
"""Load audio file from disk and return audio array and sampling rate."""
|
||||||
|
# Whisper models expect 16kHz sample rate
|
||||||
|
target_sample_rate = 16000
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Load audio file using librosa
|
# Load audio file using librosa and resample to target rate
|
||||||
audio_array, sampling_rate = librosa.load(file_path, sr=None)
|
audio_array, original_sampling_rate = librosa.load(file_path, sr=None) # type: ignore
|
||||||
logger.info(f"Loaded audio file: {file_path}, duration: {len(audio_array)/sampling_rate:.2f}s, sample rate: {sampling_rate}Hz")
|
logger.info(f"Loaded audio file: {file_path}, duration: {len(audio_array)/original_sampling_rate:.2f}s, original sample rate: {original_sampling_rate}Hz") # type: ignore
|
||||||
return audio_array, int(sampling_rate) # Ensure sampling_rate is int
|
|
||||||
|
# Resample if necessary
|
||||||
|
if original_sampling_rate != target_sample_rate:
|
||||||
|
audio_array = librosa.resample(audio_array, orig_sr=original_sampling_rate, target_sr=target_sample_rate) # type: ignore
|
||||||
|
logger.info(f"Resampled audio from {original_sampling_rate}Hz to {target_sample_rate}Hz")
|
||||||
|
|
||||||
|
return audio_array, target_sample_rate # type: ignore
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error loading audio file {file_path}: {e}")
|
logger.error(f"Error loading audio file {file_path}: {e}")
|
||||||
raise
|
raise
|
||||||
|
Loading…
x
Reference in New Issue
Block a user