i dont even know

This commit is contained in:
2026-02-04 23:30:01 +01:00
parent a06bc8f0c9
commit f09f851e31

View File

@@ -1,107 +1,145 @@
import discord import discord
from discord.ext import commands from discord.ext import commands
import speech_recognition as sr import whisper
import asyncio import asyncio
import os import os
import ctypes.util
# Konfiguracja intencji (uprawnień) # ==========================================
intents = discord.Intents.default() # 1. FIX NA OPUS (DLA ARCH LINUX / LINUXA)
intents.message_content = True # ==========================================
intents.voice_states = True # To naprawia błąd "Error occurred while decoding opus frame"
opus_path = ctypes.util.find_library('opus')
loaded_opus = False
bot = commands.Bot(command_prefix="!", intents=intents) if opus_path:
r = sr.Recognizer() print(f"✅ System znalazł bibliotekę Opus: {opus_path}")
try:
discord.opus.load_opus(opus_path)
loaded_opus = True
except Exception as e:
print(f"⚠️ Błąd ładowania systemowego Opus: {e}")
# Funkcja callback - uruchamiana po zakończeniu nagrywania if not loaded_opus:
async def finished_callback(sink, channel: discord.TextChannel, *args): # Jeśli system nie znalazł, próbujemy standardowych ścieżek
print("Nagrywanie zakończone. Przetwarzanie audio...") print("⚠️ Próba ręcznego ładowania Opus...")
libs = ['libopus.so.0', 'libopus.so', 'libopus.so.0.8.0']
# sink.audio_data.items() zwraca pary: user_id, AudioData for lib in libs:
for user_id, audio in sink.audio_data.items():
filename = f"audio_{user_id}.wav"
# Zapisz plik na dysku
with open(filename, "wb") as f:
f.write(audio.file.read()) # Używamy .read() dla pewności
# --- Reszta kodu bez zmian (rozpoznawanie mowy) ---
try: try:
with sr.AudioFile(filename) as source: discord.opus.load_opus(lib)
# Załaduj audio do pamięci print(f"✅ Załadowano ręcznie: {lib}")
audio_data = r.record(source) loaded_opus = True
# Użyj Google Web Speech API (darmowe, ale ma limity) break
text = r.recognize_google(audio_data, language="pl-PL") except:
pass
user = await bot.fetch_user(user_id)
output = f"Użytkownik {user.name} powiedział: {text}" if not loaded_opus:
print("❌ CRITICAL: Nie udało się załadować Opus via ctypes. Nagrywanie może nie działać!")
# Print do konsoli (zgodnie z prośbą)
print(output) # ==========================================
# Opcjonalnie wyślij na kanał tekstowy: # 2. KONFIGURACJA WHISPER (LOKALNE AI)
# await channel.send(output) # ==========================================
print("⏳ Ładowanie modelu Whisper (może to chwilę potrwać przy starcie)...")
# 'base' jest szybki. Jeśli chcesz super dokładności, zmień na 'small' (wolniejszy)
audio_model = whisper.load_model("base")
print("✅ Model Whisper gotowy!")
# ==========================================
# 3. KONFIGURACJA BOTA
# ==========================================
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="!", intents=intents)
async def finished_callback(sink, channel: discord.TextChannel, *args):
"""Funkcja uruchamiana PO zatrzymaniu nagrywania"""
print("⏹️ Nagrywanie zakończone. Rozpoczynam transkrypcję lokalną...")
recorded_users = sink.audio_data.items()
for user_id, audio in recorded_users:
# 1. Zapisz plik audio na dysk
filename = f"user_{user_id}.wav"
try:
with open(filename, "wb") as f:
f.write(audio.file.read())
# 2. Transkrypcja Whisperem
# fp16=False jest ważne, jeśli jedziesz na CPU, żeby nie było warningów
result = audio_model.transcribe(filename, language="pl", fp16=False)
text = result['text'].strip()
# 3. Wypisz wynik
if text:
user = await bot.fetch_user(user_id)
print(f"🎤 [ROZPOZNANO] {user.name}: {text}")
# Jeśli chcesz wysłać na czat, odkomentuj poniższe:
# await channel.send(f"**{user.name}**: {text}")
else:
print(f"🎤 [CISZA] User {user_id} nic nie powiedział.")
except sr.UnknownValueError:
print(f"Nie zrozumiano mowy użytkownika {user_id}.")
except sr.RequestError as e:
print(f"Błąd serwisu Google Speech Recognition: {e}")
except Exception as e: except Exception as e:
print(f"Wystąpił błąd: {e}") print(f"❌ Błąd podczas przetwarzania audio: {e}")
finally: finally:
# Posprzątaj pliki tymczasowe # 4. Sprzątanie plików
if os.path.exists(filename): if os.path.exists(filename):
os.remove(filename) os.remove(filename)
@bot.event @bot.event
async def on_ready(): async def on_ready():
print(f'Zalogowano jako {bot.user}') print(f'🚀 Bot zalogowany jako: {bot.user}')
print('Gotowy do działania! Użyj !join, potem !start i !stop.')
@bot.command() @bot.command()
async def join(ctx): async def join(ctx):
"""Bot dołącza do Twojego kanału głosowego""" """Wejdź na kanał głosowy"""
if ctx.author.voice: if ctx.author.voice:
channel = ctx.author.voice.channel channel = ctx.author.voice.channel
await channel.connect() await channel.connect()
await ctx.send(f"Dołączono do {channel}") await ctx.send(f"Dołączyłem do: {channel.name}")
else: else:
await ctx.send("Musisz być na kanale głosowym!") await ctx.send("Musisz być na kanale głosowym, żebym mógł dołączyć.")
@bot.command() @bot.command()
async def start(ctx): async def start(ctx):
"""Zacznij nagrywanie""" """Zacznij nagrywać"""
if ctx.voice_client: if not ctx.voice_client:
print("Rozpoczynam nagrywanie...") return await ctx.send("Nie jestem na kanale głosowym! Użyj !join")
# WaveSink nagrywa do formatu WAV
ctx.voice_client.start_recording( print("🔴 Rozpoczynam nasłuch...")
discord.sinks.WaveSink(), # WAŻNE: To wymaga biblioteki py-cord, nie starego discord.py
finished_callback, ctx.voice_client.start_recording(
ctx.channel, discord.sinks.WaveSink(), # Nagrywamy do WAV (Whisper to lubi)
) finished_callback, # Po stopie wywołaj tę funkcję
await ctx.send("Nasłuchuję... wpisz !stop aby transkrybować.") ctx.channel, # Przekaż kanał tekstowy do callbacka
else: )
await ctx.send("Bot nie jest połączony z kanałem głosowym.") await ctx.send("Nasłuchuję... (wpisz !stop aby zakończyć)")
@bot.command() @bot.command()
async def stop(ctx): async def stop(ctx):
"""Zatrzymaj nagrywanie i wypisz tekst""" """Zatrzymaj nagrywanie i przetwórz"""
if ctx.voice_client: if ctx.voice_client:
print("Zatrzymywanie nagrywania...") print("Trwa zatrzymywanie nagrywania...")
ctx.voice_client.stop_recording() ctx.voice_client.stop_recording()
await ctx.send("Zatrzymano nagrywanie. Sprawdź konsolę.") await ctx.send("Przetwarzanie nagrania... Spójrz w konsolę.")
else: else:
await ctx.send("Bot nic nie nagrywa.") await ctx.send("Nic teraz nie nagrywam.")
@bot.command() @bot.command()
async def leave(ctx): async def leave(ctx):
"""Bot wychodzi z kanału""" """Wyjdź z kanału"""
if ctx.voice_client: if ctx.voice_client:
await ctx.voice_client.disconnect() await ctx.voice_client.disconnect()
await ctx.send("Rozłączono.") await ctx.send("Nara!")
else: else:
await ctx.send("Bot nie jest połączony.") await ctx.send("Nie jestem połączony.")
# Uruchomienie
# Wstaw tutaj swój token albo ustaw zmienną środowiskową DISCORD_TOKEN
token = os.getenv("DISCORD_TOKEN")
# token = "TU_WSTAW_TOKEN_JESLI_NIE_UZYWASZ_ENV"
# Uruchom bota
token = os.getenv("DISCORD_TOKEN")
if not token: if not token:
raise SystemExit("Missing DISCORD_TOKEN environment variable. Set it and retry.") print("❌ Brak tokena! Ustaw zmienną DISCORD_TOKEN lub wpisz go w kodzie.")
else:
bot.run(token) bot.run(token)