Asad235 commited on
Commit
c80b91e
Β·
verified Β·
1 Parent(s): 6bc4753

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +110 -14
Dockerfile CHANGED
@@ -1,26 +1,122 @@
1
  FROM python:3.10-slim
2
 
3
- # Set working directory
4
- WORKDIR /app
5
-
6
- # Install system dependencies (minimal)
7
  RUN apt-get update && apt-get install -y \
8
  espeak-ng \
9
  ffmpeg \
10
- build-essential \
11
- && apt-get clean \
12
  && rm -rf /var/lib/apt/lists/*
13
 
14
- # Copy and install Python dependencies FIRST (better caching)
15
- COPY requirements.txt .
16
- RUN pip install --no-cache-dir --upgrade pip && \
17
- pip install --no-cache-dir -r requirements.txt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
- # Copy application code
20
- COPY app.py .
21
 
22
  # Expose port
23
  EXPOSE 7860
24
 
25
- # Run the app
26
- CMD ["python", "app.py"]
 
1
  FROM python:3.10-slim
2
 
3
+ # Install system dependencies
 
 
 
4
  RUN apt-get update && apt-get install -y \
5
  espeak-ng \
6
  ffmpeg \
 
 
7
  && rm -rf /var/lib/apt/lists/*
8
 
9
+ WORKDIR /app
10
+
11
+ # Create app.py with embedded code
12
+ RUN echo '"""' > app.py && \
13
+ echo 'Kokoro TTS API - Complete Single File' >> app.py && \
14
+ echo '"""' >> app.py && \
15
+ echo '' >> app.py && \
16
+ echo 'import os' >> app.py && \
17
+ echo 'import tempfile' >> app.py && \
18
+ echo 'import numpy as np' >> app.py && \
19
+ echo 'import soundfile as sf' >> app.py && \
20
+ echo 'from flask import Flask, request, jsonify, send_file' >> app.py && \
21
+ echo 'from kokoro import KPipeline' >> app.py && \
22
+ echo '' >> app.py && \
23
+ echo 'app = Flask(__name__)' >> app.py && \
24
+ echo '' >> app.py && \
25
+ echo 'print("πŸ”„ Loading Kokoro TTS Pipeline...")' >> app.py && \
26
+ echo 'pipeline = KPipeline(lang_code="a")' >> app.py && \
27
+ echo 'print("βœ… Pipeline ready!")' >> app.py && \
28
+ echo '' >> app.py && \
29
+ echo 'VOICES = {' >> app.py && \
30
+ echo ' "adam": "am_adam",' >> app.py && \
31
+ echo ' "michael": "am_michael",' >> app.py && \
32
+ echo ' "liam": "am_liam",' >> app.py && \
33
+ echo ' "bella": "af_bella",' >> app.py && \
34
+ echo ' "nicole": "af_nicole",' >> app.py && \
35
+ echo ' "emma": "bf_emma",' >> app.py && \
36
+ echo ' "george": "bm_george",' >> app.py && \
37
+ echo '}' >> app.py && \
38
+ echo '' >> app.py && \
39
+ echo '@app.route("/health", methods=["GET"])' >> app.py && \
40
+ echo 'def health_check():' >> app.py && \
41
+ echo ' return jsonify({"status": "healthy", "voices": list(VOICES.keys())})' >> app.py && \
42
+ echo '' >> app.py && \
43
+ echo '@app.route("/tts", methods=["POST"])' >> app.py && \
44
+ echo 'def text_to_speech():' >> app.py && \
45
+ echo ' try:' >> app.py && \
46
+ echo ' data = request.get_json()' >> app.py && \
47
+ echo ' if not data or "text" not in data:' >> app.py && \
48
+ echo ' return jsonify({"error": "Missing text"}), 400' >> app.py && \
49
+ echo ' text = data.get("text", "")' >> app.py && \
50
+ echo ' voice_key = data.get("voice", "adam")' >> app.py && \
51
+ echo ' speed = float(data.get("speed", 1.0))' >> app.py && \
52
+ echo ' if voice_key not in VOICES:' >> app.py && \
53
+ echo ' voice_key = "adam"' >> app.py && \
54
+ echo ' voice = VOICES[voice_key]' >> app.py && \
55
+ echo ' audio_chunks = []' >> app.py && \
56
+ echo ' generator = pipeline(text, voice=voice, speed=speed)' >> app.py && \
57
+ echo ' for _, _, audio in generator:' >> app.py && \
58
+ echo ' audio_chunks.append(audio)' >> app.py && \
59
+ echo ' if not audio_chunks:' >> app.py && \
60
+ echo ' return jsonify({"error": "Generation failed"}), 500' >> app.py && \
61
+ echo ' full_audio = np.concatenate(audio_chunks)' >> app.py && \
62
+ echo ' temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")' >> app.py && \
63
+ echo ' sf.write(temp_file.name, full_audio, 24000)' >> app.py && \
64
+ echo ' return send_file(temp_file.name, mimetype="audio/wav", as_attachment=True, download_name="speech.wav")' >> app.py && \
65
+ echo ' except Exception as e:' >> app.py && \
66
+ echo ' return jsonify({"error": str(e)}), 500' >> app.py && \
67
+ echo '' >> app.py && \
68
+ echo '@app.route("/", methods=["GET"])' >> app.py && \
69
+ echo 'def index():' >> app.py && \
70
+ echo ' return """' >> app.py && \
71
+ echo '<!DOCTYPE html>' >> app.py && \
72
+ echo '<html>' >> app.py && \
73
+ echo '<head><title>Kokoro TTS API</title>' >> app.py && \
74
+ echo '<style>' >> app.py && \
75
+ echo 'body{font-family:Arial;max-width:800px;margin:50px auto;padding:20px;background:#1a1a2e;color:#fff}' >> app.py && \
76
+ echo 'textarea,select,input{width:100%;padding:10px;margin:10px 0;border-radius:5px;border:none}' >> app.py && \
77
+ echo 'button{background:#4ecdc4;color:#fff;padding:10px 20px;border:none;border-radius:5px;cursor:pointer}' >> app.py && \
78
+ echo '.result{margin-top:20px;padding:20px;background:#2d2d44;border-radius:10px}' >> app.py && \
79
+ echo 'audio{width:100%;margin-top:10px}' >> app.py && \
80
+ echo '</style>' >> app.py && \
81
+ echo '</head>' >> app.py && \
82
+ echo '<body>' >> app.py && \
83
+ echo '<h1>🎀 Kokoro TTS API</h1>' >> app.py && \
84
+ echo '<textarea id="text" rows="5" placeholder="Enter your text...">Hello! This is a test.</textarea>' >> app.py && \
85
+ echo '<select id="voice"><option value="adam">Adam (Male)</option><option value="bella">Bella (Female)</option></select>' >> app.py && \
86
+ echo '<input type="range" id="speed" min="0.8" max="1.2" step="0.05" value="1.0">' >> app.py && \
87
+ echo '<button onclick="generate()">Generate Speech</button>' >> app.py && \
88
+ echo '<div id="result" class="result" style="display:none"><h3>Generated Audio:</h3><audio id="audio" controls></audio></div>' >> app.py && \
89
+ echo '<script>' >> app.py && \
90
+ echo 'async function generate(){' >> app.py && \
91
+ echo 'const text=document.getElementById("text").value;' >> app.py && \
92
+ echo 'const voice=document.getElementById("voice").value;' >> app.py && \
93
+ echo 'const speed=parseFloat(document.getElementById("speed").value);' >> app.py && \
94
+ echo 'if(!text){alert("Enter text");return;}' >> app.py && \
95
+ echo 'const res=await fetch("/tts",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({text,voice,speed})});' >> app.py && \
96
+ echo 'if(res.ok){const blob=await res.blob();const url=URL.createObjectURL(blob);document.getElementById("audio").src=url;document.getElementById("result").style.display="block";}' >> app.py && \
97
+ echo 'else{alert("Error");}}' >> app.py && \
98
+ echo '</script></body></html>' >> app.py && \
99
+ echo '"""' >> app.py && \
100
+ echo '' >> app.py && \
101
+ echo 'if __name__ == "__main__":' >> app.py && \
102
+ echo ' port = int(os.environ.get("PORT", 7860))' >> app.py && \
103
+ echo ' print(f"πŸš€ Server on port {port}")' >> app.py && \
104
+ echo ' app.run(host="0.0.0.0", port=port)' >> app.py
105
+
106
+ # Create requirements.txt
107
+ RUN echo "flask==2.3.3" > requirements.txt && \
108
+ echo "gunicorn==21.2.0" >> requirements.txt && \
109
+ echo "kokoro==0.8.0" >> requirements.txt && \
110
+ echo "soundfile==0.12.1" >> requirements.txt && \
111
+ echo "numpy==1.24.3" >> requirements.txt && \
112
+ echo "torch==2.1.0" >> requirements.txt && \
113
+ echo "torchaudio==2.1.0" >> requirements.txt
114
 
115
+ # Install Python dependencies
116
+ RUN pip install --no-cache-dir -r requirements.txt
117
 
118
  # Expose port
119
  EXPOSE 7860
120
 
121
+ # Run with gunicorn
122
+ CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:7860"]