Peiiiiiiiiru's picture
Update app.py
77c1c41 verified
import gradio as gr
from openai import OpenAI
import os
import random
import zipfile
import json
from gtts import gTTS
from pydub import AudioSegment, effects
from vosk import Model, KaldiRecognizer
import wave
# Set OpenAI API Key
client = OpenAI(api_key=os.getenv("sk-tHjndptHgYkaZY6RTPZh-sWkkd318Nqor5qPsyPoqWT3BlbkFJQgnwmTeMnI0VhKOmYv-XLXTWSll-Nan80ZlQiEbT0A"))
# Extract background music file from zip with random selection
def unzip_random_background_music(zip_path="background_music.mp3.zip", extract_folder="audio_files"):
if not os.path.exists(extract_folder):
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
zip_ref.extractall(extract_folder)
music_files = [f for f in os.listdir(extract_folder) if f.endswith(".mp3")]
if not music_files:
raise FileNotFoundError("解壓後未找到 MP3 音樂檔案。")
return os.path.join(extract_folder, random.choice(music_files)) # Randomly select a music file
# Generate text response using OpenAI API with Nonviolent and Interpersonal Communication Theory
def generate_response(input_text, language="zh"):
system_prompt = (
"你是一個根據非暴力溝通和人際溝通理論提供建議的溫暖助理,"
"請用同理心和鼓勵的語氣,分析情況並給出撫慰人心的建議,促進理解和情緒表達。"
"請使用輸入語言回應,並讓回應充滿關懷和支持。"
)
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": input_text}
]
)
return response.choices[0].message.content
# Generate audio response combined with background music (plays entire music)
def generate_audio_with_music(input_text, language="zh"):
try:
# Unzip and randomly load background music
background_music_path = unzip_random_background_music()
# Generate text response
text_response = generate_response(input_text, language)
# Generate TTS audio
tts = gTTS(text=text_response, lang=language)
tts.save("response.mp3")
response_audio = AudioSegment.from_file("response.mp3")
response_audio = effects.normalize(response_audio) # Normalize response audio
# Load background music and ensure it plays entirely
background_music = AudioSegment.from_file(background_music_path)
background_music = background_music.set_channels(1).set_frame_rate(16000) # Ensure consistent format
background_music = background_music - 10 # Reduce background volume for balance
# Extend background music to play after TTS audio ends
extended_music = background_music[:]
if len(background_music) < len(response_audio):
extended_music = background_music * (len(response_audio) // len(background_music) + 1)
extended_music = extended_music[:len(response_audio)]
combined_audio = response_audio.overlay(extended_music, position=0)
# Export final audio
final_audio_path = "final_audio.mp3"
combined_audio.export(final_audio_path, format="mp3")
return text_response, final_audio_path
except Exception as e:
return f"Error: {str(e)}", None
# Transcribe speech input to text with Vosk model
def transcribe_speech(audio_file):
try:
model_path = "model/vosk-model-small-zh" # Vosk model path
if not os.path.exists(model_path):
return "Vosk 模型未找到,請確認模型已下載並存放於正確目錄。"
# Convert audio to required format
audio = AudioSegment.from_file(audio_file)
audio = audio.set_channels(1).set_frame_rate(16000)
audio.export("temp.wav", format="wav")
wf = wave.open("temp.wav", "rb")
model = Model(model_path)
recognizer = KaldiRecognizer(model, wf.getframerate())
while True:
data = wf.readframes(4000)
if len(data) == 0:
break
recognizer.AcceptWaveform(data)
result = json.loads(recognizer.Result())
return result.get("text", "")
except Exception as e:
return f"語音辨識出錯: {str(e)}"
# Generate today's lucky item
def generate_lucky_item(happiness, energy, focus):
colors = ["紅色", "藍色", "綠色", "黃色", "紫色"]
items = ["手環", "水晶", "書籍", "杯子", "植物"]
foods = ["巧克力", "咖啡", "水果", "餅乾", "堅果"]
numbers = list(range(1, 100))
lucky_color = random.choice(colors)
lucky_item = random.choice(items)
lucky_food = random.choice(foods)
lucky_number = random.choice(numbers)
return {
"顏色": lucky_color,
"物品": lucky_item,
"食物": lucky_food,
"數字": lucky_number
}
# Gradio interface
def main():
with gr.Blocks(css="""
body {
background: url('https://www.transparenttextures.com/patterns/asfalt-light.png');
background-color: #F5F0E6;
}
.gr-button {
background-color: #E8C1A0;
color: #5A4A42;
border-radius: 10px;
}
.gr-button:hover {
background-color: #D1A582;
color: #FFF;
}
""") as demo:
gr.Markdown("""
# 🌸 心靈對話※情感療癒平台 🌸
### 🌟 讓我們攜手解開心繫,聽聽您心底的聲音-請你相信沒有人是座孤島 🌟
""")
with gr.Row():
input_text = gr.Textbox(label="💼 請輸入問題或心情")
audio_input = gr.Audio(label="🎤 說出您的心聲", type="filepath")
submit_button = gr.Button("💖 傳遞您的心聲 💖")
output_text = gr.Textbox(label="📜 回應內容")
output_audio = gr.Audio(label="🎵 播放療癒語音")
def process_input(text, audio):
detected_language = "zh" # Default language
if audio:
text = transcribe_speech(audio)
if not text:
return "辨識失敗,請重新錄音", None
detected_language = "zh"
return generate_audio_with_music(text, detected_language)
submit_button.click(fn=process_input, inputs=[input_text, audio_input], outputs=[output_text, output_audio])
gr.Markdown("""
## 調整您的心情指數來生成今日幸運小物!
""")
with gr.Row():
happiness_slider = gr.Slider(0, 100, label="💖 快樂指數")
energy_slider = gr.Slider(0, 100, label="⚡ 能量指數")
focus_slider = gr.Slider(0, 100, label="🎯 專注指數")
lucky_button = gr.Button("🔮 生成今日幸運小物!")
lucky_output = gr.Textbox(label="🎁 今日幸運小物")
def process_lucky(happiness, energy, focus):
lucky_item = generate_lucky_item(happiness, energy, focus)
return json.dumps(lucky_item, ensure_ascii=False, indent=2)
lucky_button.click(fn=process_lucky, inputs=[happiness_slider, energy_slider, focus_slider], outputs=lucky_output)
demo.launch()
if __name__ == "__main__":
main()