feat: web UI + QR login + portable build
- Add web UI panel (dark theme) at / with REST API - Add Bilibili QR code scan login with browser header emulation - Add wanakana for English -> katakana conversion - Add volume control (0%-200%) - Add message format with '说、' pause marker - PyInstaller --onedir build for portable exe - Rate-limit danmaku logging (1/20) - Fix aiohttp.access log spam - Add README.md
This commit is contained in:
+7
-14
@@ -4,35 +4,28 @@ import asyncio
|
||||
import io
|
||||
import logging
|
||||
|
||||
import numpy as np
|
||||
import sounddevice as sd
|
||||
import soundfile as sf
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def play_wav(wav_data: bytes) -> None:
|
||||
"""Play WAV audio data synchronously (blocking).
|
||||
|
||||
Args:
|
||||
wav_data: Raw WAV file bytes.
|
||||
"""
|
||||
def play_wav(wav_data: bytes, volume: int = 100) -> None:
|
||||
data, samplerate = sf.read(io.BytesIO(wav_data), dtype="float32")
|
||||
if volume != 100:
|
||||
gain = max(0.0, volume / 100.0)
|
||||
data = np.clip(data * gain, -1.0, 1.0)
|
||||
sd.play(data, samplerate)
|
||||
sd.wait()
|
||||
|
||||
|
||||
async def play_wav_async(wav_data: bytes) -> None:
|
||||
"""Play WAV audio data asynchronously.
|
||||
|
||||
Args:
|
||||
wav_data: Raw WAV file bytes.
|
||||
"""
|
||||
async def play_wav_async(wav_data: bytes, volume: int = 100) -> None:
|
||||
loop = asyncio.get_running_loop()
|
||||
await loop.run_in_executor(None, play_wav, wav_data)
|
||||
await loop.run_in_executor(None, play_wav, wav_data, volume)
|
||||
|
||||
|
||||
def get_output_devices() -> list[dict]:
|
||||
"""List available audio output devices."""
|
||||
devices = sd.query_devices()
|
||||
result = []
|
||||
for i, dev in enumerate(devices):
|
||||
|
||||
Reference in New Issue
Block a user