Calvin commited on
Commit
f707d78
·
1 Parent(s): 0cf41d1

change model

Browse files
Files changed (2) hide show
  1. app.py +23 -31
  2. requirements.txt +0 -1
app.py CHANGED
@@ -1,5 +1,5 @@
1
  from fastapi import FastAPI
2
- from transformers import VitsModel, AutoTokenizer
3
  import torch
4
  import aiofiles
5
  import uvicorn
@@ -8,29 +8,20 @@ import soundfile as sf
8
 
9
  app = FastAPI()
10
 
11
- # Load model once at startup
12
- model_name = "Ellbendls/csm-1b-indonesian-fine-tuned"
13
- model = VitsModel.from_pretrained(model_name)
14
- tokenizer = AutoTokenizer.from_pretrained(model_name)
 
15
 
16
  def generate_timestamps(script: str, wpm: int = 150):
17
  sentences = [s.strip() for s in script.replace("\n", " ").split(".") if s.strip()]
18
- timestamps = []
19
- current_time = 0.0
20
- seconds_per_word = 60.0 / wpm
21
-
22
- for sentence in sentences:
23
- word_count = len(sentence.split())
24
- duration = round(word_count * seconds_per_word, 2)
25
- start_time = round(current_time, 2)
26
- end_time = round(current_time + duration, 2)
27
- timestamps.append({
28
- "sentence": sentence,
29
- "start": start_time,
30
- "end": end_time
31
- })
32
- current_time += duration
33
-
34
  return timestamps
35
 
36
  @app.get("/")
@@ -38,19 +29,20 @@ async def root():
38
  return {"message": "API is running!"}
39
 
40
  @app.post("/tts")
41
- async def text_to_speech(payload: dict):
42
  text = payload.get("text", "")
43
-
44
  if not text:
45
  return {"error": "Text is required"}
46
 
47
  file_path = "output.wav"
48
- inputs = tokenizer(text, return_tensors="pt")
49
- with torch.no_grad():
50
- output = model(**inputs).waveform
51
- sf.write(file_path, output.squeeze().cpu().numpy(), model.config.sampling_rate)
 
 
52
 
53
- async with aiofiles.open(file_path, mode="rb") as f:
54
  audio_data = await f.read()
55
 
56
  return {
@@ -62,10 +54,10 @@ async def text_to_speech(payload: dict):
62
 
63
  @app.get("/download/{filename}")
64
  async def download_file(filename: str):
65
- file_path = os.path.join(os.getcwd(), filename)
66
- if os.path.exists(file_path):
67
  from fastapi.responses import FileResponse
68
- return FileResponse(file_path, media_type="audio/wav", filename=filename)
69
  return {"error": "File not found"}
70
 
71
  if __name__ == "__main__":
 
1
  from fastapi import FastAPI
2
+ from transformers import CsmForConditionalGeneration, AutoProcessor
3
  import torch
4
  import aiofiles
5
  import uvicorn
 
8
 
9
  app = FastAPI()
10
 
11
+ # Load model and processor once
12
+ MODEL_NAME = "Ellbendls/csm-1b-indonesian-fine-tuned"
13
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
14
+ model = CsmForConditionalGeneration.from_pretrained(MODEL_NAME).to(device)
15
+ processor = AutoProcessor.from_pretrained(MODEL_NAME)
16
 
17
  def generate_timestamps(script: str, wpm: int = 150):
18
  sentences = [s.strip() for s in script.replace("\n", " ").split(".") if s.strip()]
19
+ timestamps, current = [], 0.0
20
+ spw = 60.0 / wpm
21
+ for s in sentences:
22
+ dur = round(len(s.split()) * spw, 2)
23
+ timestamps.append({"sentence": s, "start": round(current,2), "end": round(current+dur,2)})
24
+ current += dur
 
 
 
 
 
 
 
 
 
 
25
  return timestamps
26
 
27
  @app.get("/")
 
29
  return {"message": "API is running!"}
30
 
31
  @app.post("/tts")
32
+ async def tts_api(payload: dict):
33
  text = payload.get("text", "")
 
34
  if not text:
35
  return {"error": "Text is required"}
36
 
37
  file_path = "output.wav"
38
+ input_text = f"[0]{text}"
39
+ inputs = processor(input_text, return_tensors="pt").to(device)
40
+ outputs = model.generate(**inputs, max_new_tokens=200, output_audio=True)
41
+ audio = outputs[0].detach().cpu().numpy()
42
+
43
+ sf.write(file_path, audio, 24000)
44
 
45
+ async with aiofiles.open(file_path, "rb") as f:
46
  audio_data = await f.read()
47
 
48
  return {
 
54
 
55
  @app.get("/download/{filename}")
56
  async def download_file(filename: str):
57
+ fp = os.path.join(os.getcwd(), filename)
58
+ if os.path.exists(fp):
59
  from fastapi.responses import FileResponse
60
+ return FileResponse(fp, media_type="audio/wav", filename=filename)
61
  return {"error": "File not found"}
62
 
63
  if __name__ == "__main__":
requirements.txt CHANGED
@@ -4,6 +4,5 @@ aiofiles
4
  pydantic
5
  transformers
6
  torch
7
- torchaudio
8
  soundfile
9
  sentencepiece
 
4
  pydantic
5
  transformers
6
  torch
 
7
  soundfile
8
  sentencepiece