Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ venv.bak/

*.h5
__pycache__/
*.pyc
*.pyc
audio/
125 changes: 62 additions & 63 deletions app/controller/RecordController.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
import os
import subprocess
import time
from typing import List

import requests

from fastapi import APIRouter, Request, UploadFile, File, Form
from boto3 import client
from pydub import AudioSegment
from pydub.playback import play

from app import s3Service
from app.dto.BasicTTSRequestDto import BasicTTSRequestDto
from app.dto.FirstTTSRequestDto import FirstTTSRequestDto
from app.dto.ExtraTTSRequestDto import ExtraTTSRequestDto
from fastapi import APIRouter, Request, UploadFile, File, Form

from app.elevenLabs import add_voice, text_to_speech_file_save_AWS, get_voice, delete_all_voice, text_to_speech_file
from app.s3Service import download_from_s3_links, download_from_s3
from app.dto.ScheduleSpeakRequestDto import ScheduleSpeakRequestDto
from app.dto.ScheduleTTSRequestDto import ScheduleTTSRequestDto
from app.service.elevenLabs import text_to_speech_file_save_AWS
from app.service.gpt import ChatgptAPI
from app.service.s3Service import download_from_s3
from app.utils import play_file

router = APIRouter(
prefix="/api/fastapi",
Expand All @@ -36,6 +30,18 @@
)


async def save_local_file(file: UploadFile) -> str:
"""하나의 파일을 로컬에 저장하고 경로를 반환합니다."""
audio_dir = "./audio"
if not os.path.exists(audio_dir):
os.makedirs(audio_dir)

local_file_path = os.path.join(audio_dir, file.filename)
with open(local_file_path, "wb") as f:
f.write(await file.read())
return local_file_path


async def save_local_files(files: List[UploadFile]) -> list:
"""업로드된 파일을 로컬에 저장하고 파일 경로를 반환합니다."""
audio_dir = "./audio"
Expand All @@ -50,73 +56,55 @@ async def save_local_files(files: List[UploadFile]) -> list:
return local_file_path_list


# 첫 로그인 시 1분 목소리 녹음 api
# 첫 로그인 시 목소리 녹음 api
@router.post("/voices")
async def getVoice(request: Request, files: List[UploadFile] = File(...)):
# token = request.headers.get("Authorization").split(" ")[1]
local_file_path_list = await save_local_files(files)
name = 'yjg'
voice_id = add_voice(name=name, local_file_paths=local_file_path_list)
print(voice_id)
async def getVoice(request: Request, user_id: int = Form(...), file: UploadFile = File(...)):
token = request.headers.get("Authorization").split(" ")[1]
local_file_path = await save_local_file(file)
name = str(user_id)
# voice_id = add_voice(name=name, local_file_paths=[local_file_path])
print(name)
# voice_url = s3Service.upload_to_s3(local_file_path)
# os.remove(local_file_path)
os.remove(local_file_path)

# send_user_voice_file_to_spring(token=token, voice_url=voice_url)
send_user_voice_id_to_spring(token=token, voice_id=yjg_voice_id)


@router.post("/save/basic-tts")
async def save_S3_basic_tts(request: Request, firstTTSRequestDtoList: FirstTTSRequestDto):
@router.post("/schedules")
async def schedule_tts(request: Request, schedules: ScheduleTTSRequestDto):
# token = request.headers.get("Authorization").split(" ")[1]
# text가 어떤형식으로 올지 몰라서 일단 그대로 내보낸다고 가정 (변환시 지피티 사용)
voice_id = schedules.voice_id

prompt = ChatgptAPI(schedules.schedule_text, schedules.alias)

# schedule_dict: {"저녁": "엄마~ 저녁 잘 챙겨 먹었어?", "운동": "오늘 운동했어? 건강 챙겨~!"}
schedule_dict = prompt.get_schedule_json()

# TTS 처리 (MP3 파일 생성 후 s3 저장)
response = {
firstTTSRequestDtoList.basic_schedule_id[i]: text_to_speech_file_save_AWS(firstTTSRequestDtoList.basic_schedule_text[i],
yjg_voice_id)
for i in range(len(firstTTSRequestDtoList.basic_schedule_id))
schedules.schedule_id[i]: {
"keyword": schedules.schedule_text[i], # 키워드 직접 저장
"text": schedule_dict.get(schedules.schedule_text[i], ""), # 문장은 GPT 결과에서 매핑
"url": text_to_speech_file_save_AWS(
schedule_dict.get(schedules.schedule_text[i], ""),
yjg_voice_id
)
}
for i in range(len(schedules.schedule_id))
}

return response


@router.post("/basic-tts")
async def speak_schedule_tts(request: Request, basicTTSRequestDto: BasicTTSRequestDto):
@router.post("/schedules-speak")
async def speak_schedule(request: Request, scheduleSpeakRequestDto: ScheduleSpeakRequestDto):
# token = request.headers.get("Authorization").split(" ")[1]
local_file_path = download_from_s3(basicTTSRequestDto.schedule_voice_Url)
local_file_path = download_from_s3(scheduleSpeakRequestDto.schedule_voice_Url)
print(f"Downloaded file path: {local_file_path}")

# 블루투스 헤드셋 또는 기본 스피커로 출력
os.system("pactl list sinks | grep 'bluez_sink'") # 블루투스 출력 장치 확인
os.system("pactl set-default-sink `pactl list sinks short | grep bluez_sink | awk '{print $2}'`") # 기본 출력 변경
# target_time에 맞춰서 TTS 파일 재생
play_file.play_at_target_time(scheduleSpeakRequestDto.target_time, local_file_path)

# 로컬 파일을 직접 재생
subprocess.run(["mpg321", local_file_path])

return {"message": "TTS completed and played on Bluetooth headset or speaker"}


@router.post("/extra-tts")
async def speak_schedule_tts(request: Request, extraTTSRequestDto: ExtraTTSRequestDto):
# token = request.headers.get("Authorization").split(" ")[1]
schedule_text = extraTTSRequestDto.schedule_text

#진짜 실제로 쓸 코드
local_file_path = text_to_speech_file(schedule_text, yjg_voice_id)

# 테스트하면서 AWS에 올려놓으려고 남긴 코드
url = text_to_speech_file_save_AWS(schedule_text, yjg_voice_id)
local_file_path = download_from_s3(url)

# local_file_path = os.getcwd()+"/test_audio/test8.mp3" # test
# 블루투스 헤드셋 또는 기본 스피커로 출력
os.system("pactl list sinks | grep 'bluez_sink'") # 블루투스 출력 장치 확인
os.system("pactl set-default-sink `pactl list sinks short | grep bluez_sink | awk '{print $2}'`") # 기본 출력 변경

# 로컬 파일을 직접 재생
subprocess.run(["/usr/bin/mpg321", local_file_path])
# subprocess.run(["ffplay", "-nodisp", "-autoexit", local_file_path],
# stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) # 윈도우용
return {"message": "TTS completed and played on Bluetooth headset or speaker"}
return {"message": "TTS completed and played on speaker"}


def send_user_voice_file_to_spring(token: str, voice_url: str):
Expand All @@ -130,6 +118,17 @@ def send_user_voice_file_to_spring(token: str, voice_url: str):
# requests.post("https://peachmentor.com/api/spring/records/voices", headers=headers, json=data)


def send_user_voice_id_to_spring(token: str, voice_id: str):
headers = {
"Authorization": f"Bearer {token}"
}
data = {
"voiceId": voice_id
}
requests.post("http://localhost:8080/api/spring/records/voices", headers=headers, json=data)
# requests.post("https://peachmentor.com/api/spring/records/voices", headers=headers, json=data)


def send_user_speech_file_to_spring(token: str, before_audio_link: str, answerId: int):
headers = {
"Authorization": f"Bearer {token}"
Expand Down
11 changes: 0 additions & 11 deletions app/convertFileExtension.py

This file was deleted.

10 changes: 0 additions & 10 deletions app/dto/BasicTTSRequestDto.py

This file was deleted.

3 changes: 0 additions & 3 deletions app/dto/ExtraTTSRequestDto.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import List

from pydantic import BaseModel


Expand All @@ -8,4 +6,3 @@ class ExtraTTSRequestDto(BaseModel):
is_basic_schedule: bool
schedule_text: str
target_time: str # "10:00:00" 형식

8 changes: 0 additions & 8 deletions app/dto/FirstTTSRequestDto.py

This file was deleted.

7 changes: 7 additions & 0 deletions app/dto/ScheduleSpeakRequestDto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from pydantic import BaseModel


class ScheduleSpeakRequestDto(BaseModel):
schedule_id: int
schedule_voice_Url: str
target_time: str # "10:00:00" 형식
10 changes: 10 additions & 0 deletions app/dto/ScheduleTTSRequestDto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from typing import List

from pydantic import BaseModel


class ScheduleTTSRequestDto(BaseModel):
voice_id: int
alias: str
schedule_id: List[int]
schedule_text: List[str]
88 changes: 0 additions & 88 deletions app/gpt.py

This file was deleted.

19 changes: 10 additions & 9 deletions app/elevenLabs.py → app/service/elevenLabs.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import os
import uuid
from elevenlabs import ElevenLabs, VoiceSettings

from dotenv import load_dotenv
from elevenlabs import ElevenLabs, VoiceSettings

from app.s3Service import upload_to_s3
from app.service.s3Service import upload_to_s3

load_dotenv()
client = ElevenLabs(
Expand Down Expand Up @@ -46,13 +47,13 @@ def text_to_speech_file_save_AWS(text: str, voice_id: str) -> str:
voice_id=voice_id,
output_format="mp3_22050_32",
text=text,
model_id="eleven_turbo_v2_5",
voice_settings=VoiceSettings(
stability=0.3,
similarity_boost=1.0,
style=0.0,
use_speaker_boost=True,
),
model_id="eleven_multilingual_v2",
# voice_settings=VoiceSettings(
# stability=0.3,
# similarity_boost=1.0,
# style=0.0,
# use_speaker_boost=True,
# ),
)

save_file_path = f"{uuid.uuid4()}.mp3"
Expand Down
Loading