osnarayana commited on
Commit
38822a8
Β·
1 Parent(s): ca042ba

Fix: use /tmp for audio generation to avoid permission errors

Browse files
.gitignore CHANGED
@@ -41,4 +41,7 @@ __pycache__/
41
  outputs/
42
  generated/
43
  *.pyc
44
- *.log
 
 
 
 
41
  outputs/
42
  generated/
43
  *.pyc
44
+ *.log
45
+
46
+ #adding tmp files
47
+ /tmp/hf_cache
app/api/v1/audio.py CHANGED
@@ -1,9 +1,9 @@
1
- from fastapi import APIRouter, HTTPException, Body
2
- from fastapi.responses import Response # βœ… add this
 
3
  from pydantic import BaseModel
4
- from gtts import gTTS
5
- import uuid
6
- import os
7
  router = APIRouter()
8
 
9
  class AudioRequest(BaseModel):
@@ -12,23 +12,9 @@ class AudioRequest(BaseModel):
12
  language: str = "en"
13
 
14
  @router.post("/generate")
15
- def generate_audio_endpoint(payload: AudioRequest):
16
  try:
17
- # βœ… Save inside generated/audio for consistency
18
- filename = f"audio_{uuid.uuid4().hex}.mp3"
19
- folder = "generated/audio"
20
- os.makedirs("generated_audio", exist_ok=True)
21
- file_path = f"generated_audio/{filename}" # βœ… match your video & image folders
22
-
23
- # βœ… Generate TTS audio
24
- tts = gTTS(text=payload.text, lang=payload.language)
25
- tts.save(file_path)
26
-
27
- # βœ… Return audio bytes for inline Streamlit playback
28
- with open(file_path, "rb") as f:
29
- audio_bytes = f.read()
30
-
31
- return Response(content=audio_bytes, media_type="audio/mpeg")
32
-
33
  except Exception as e:
34
  raise HTTPException(status_code=500, detail=str(e))
 
1
+ # app/api/v1/audio.py
2
+ from fastapi import APIRouter, HTTPException
3
+ from fastapi.responses import FileResponse
4
  from pydantic import BaseModel
5
+ from app.services.audio_service import generate_audio_file
6
+
 
7
  router = APIRouter()
8
 
9
  class AudioRequest(BaseModel):
 
12
  language: str = "en"
13
 
14
  @router.post("/generate")
15
+ def generate_audio(payload: AudioRequest):
16
  try:
17
+ file_path = generate_audio_file(payload.text, payload.language)
18
+ return FileResponse(file_path, media_type="audio/mpeg", filename="output.mp3")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  except Exception as e:
20
  raise HTTPException(status_code=500, detail=str(e))
app/services/audio_service.py CHANGED
@@ -1,39 +1,18 @@
1
  # app/services/audio_service.py
2
  from gtts import gTTS
3
- import os
4
- from datetime import datetime
5
- from app.db import SessionLocal
6
- from app.models import MediaGeneration
7
- import logging
8
  logger = logging.getLogger(__name__)
9
- import uuid
10
 
11
- def generate_audio_file(text: str, voice: str = "default", language: str = "en") -> str:
 
12
  try:
 
 
13
  tts = gTTS(text=text, lang=language, slow=False)
14
- timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
15
- filename = f"audio_{timestamp}.mp3"
16
- output_dir = "generated/audio"
17
- os.makedirs(output_dir, exist_ok=True)
18
- file_path = os.path.join(output_dir, filename)
19
  tts.save(file_path)
20
- logger.info(f"Generated Audio: {filename}")
21
  return file_path
22
- except:
23
  logger.error(f"Audio Generation Failed: {str(e)}")
24
  raise
25
-
26
-
27
- from app.db import SessionLocal
28
- from app.models import MediaGeneration
29
-
30
- def save_metadata(media_type, prompt, file_path):
31
- db = SessionLocal()
32
- record = MediaGeneration(
33
- media_type=media_type,
34
- prompt=prompt,
35
- file_path=file_path,
36
- )
37
- db.add(record)
38
- db.commit()
39
- db.close()
 
1
  # app/services/audio_service.py
2
  from gtts import gTTS
3
+ import os, uuid, logging
4
+
 
 
 
5
  logger = logging.getLogger(__name__)
 
6
 
7
+ def generate_audio_file(text: str, language: str = "en") -> str:
8
+ """Generate an MP3 file in Hugging Face writable /tmp directory."""
9
  try:
10
+ os.makedirs("/tmp", exist_ok=True)
11
+ file_path = os.path.join("/tmp", f"audio_{uuid.uuid4().hex}.mp3")
12
  tts = gTTS(text=text, lang=language, slow=False)
 
 
 
 
 
13
  tts.save(file_path)
14
+ logger.info(f"Generated Audio: {file_path}")
15
  return file_path
16
+ except Exception as e:
17
  logger.error(f"Audio Generation Failed: {str(e)}")
18
  raise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
auto_test_endpoints.py CHANGED
@@ -1,83 +1,103 @@
1
  import requests
2
  import json
3
  import os
 
 
4
 
5
  BASE_URL = "https://osnarayana-media-gen-api.hf.space"
6
- TOKEN = "my_secure_token_123"
7
-
8
- headers = {"Authorization": f"Bearer {TOKEN}"}
9
-
10
-
11
- def fetch_openapi_schema():
12
- """Fetch Swagger/OpenAPI schema from FastAPI"""
13
- url = f"{BASE_URL}/openapi.json"
14
- resp = requests.get(url)
15
- resp.raise_for_status()
16
- return resp.json()
17
-
18
-
19
- def guess_payload(path):
20
- """Generate dummy payloads based on endpoint path"""
21
- path_lower = path.lower()
22
- if "image" in path:
 
 
 
 
 
 
 
 
 
23
  return {"prompt": "A cute cat in watercolor style"}
24
- if "audio" in path:
25
- return {"text": "Hello from Hugging Face Space!"}
26
- if "video" in path:
27
- return {"prompt": "A futuristic city with flying cars"}
28
- if "metrics" in path and "bleu" in path:
 
 
 
 
29
  return {"reference": "hello world", "candidate": "hello"}
30
- if "metrics" in path and "clipscore" in path:
31
  return {"reference": "a photo of a cat", "candidate": "an image of a cute cat"}
32
- # fallback
33
  return {}
34
 
35
-
36
- def save_response_content(resp, path):
37
- """Save binary content for media endpoints"""
38
- content_type = resp.headers.get("content-type", "")
39
- filename = None
40
- if "image" in content_type:
41
- filename = "output_image.png"
42
- elif "audio" in content_type:
43
- filename = "output_audio.mp3"
44
- elif "video" in content_type:
45
- filename = "output_video.mp4"
46
-
47
- if filename:
48
- with open(filename, "wb") as f:
49
- f.write(resp.content)
50
- print(f"βœ… Saved file: {filename}")
51
-
52
-
53
- def test_all_endpoints():
54
- schema = fetch_openapi_schema()
55
- paths = schema.get("paths", {})
56
-
57
- for path, methods in paths.items():
58
- for method, details in methods.items():
59
- # Only test POST endpoints for now
60
- if method.lower() != "post":
61
- continue
62
-
63
- url = BASE_URL + path
64
- payload = guess_payload(path)
65
-
66
- print(f"\nTesting {method.upper()} {url} with payload: {payload}")
67
- # Decide if we need JSON or query params (FastAPI default body)
68
- resp = requests.post(url, headers=headers, json=payload)
69
-
70
- print(f"Status: {resp.status_code}")
71
- if resp.status_code == 200:
72
- # Try to save file if it's media
73
- save_response_content(resp, path)
74
- try:
75
- print("Response JSON:", resp.json())
76
- except Exception:
77
- print("Non-JSON response saved as file")
78
- else:
79
- print("Error Response:", resp.text)
80
-
81
-
82
- if __name__ == "__main__":
83
- test_all_endpoints()
 
 
 
 
 
 
 
1
  import requests
2
  import json
3
  import os
4
+ import time
5
+ from datetime import datetime
6
 
7
  BASE_URL = "https://osnarayana-media-gen-api.hf.space"
8
+ TOKEN = "my_secure_token_123" # must match your auth.py
9
+
10
+ headers = {
11
+ "Authorization": f"Bearer {TOKEN}",
12
+ "Content-Type": "application/json"
13
+ }
14
+
15
+ # Directory for saving media files
16
+ os.makedirs("outputs", exist_ok=True)
17
+
18
+ def unique_filename(prefix, ext):
19
+ ts = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
20
+ return os.path.join("outputs", f"{prefix}_{ts}.{ext}")
21
+
22
+ # Dummy payload generator
23
+ def get_dummy_payload(path):
24
+ if "audio/generate" in path:
25
+ return {"text": "Hello from auto test!"}
26
+ elif "video/generate" in path:
27
+ return {
28
+ "prompt": "A futuristic city with flying cars",
29
+ "tone": "inspiring",
30
+ "domain": "sci-fi",
31
+ "environment": "day"
32
+ }
33
+ elif "image/generate" in path:
34
  return {"prompt": "A cute cat in watercolor style"}
35
+ elif "ppt/generate" in path:
36
+ return {
37
+ "slides": [
38
+ {"title": "Welcome", "content": "This is auto-generated PPT"},
39
+ {"title": "Conclusion", "content": "Demo slide"}
40
+ ]
41
+ }
42
+ elif "metrics/evaluate/bleu" in path:
43
+ # metrics currently require query params
44
  return {"reference": "hello world", "candidate": "hello"}
45
+ elif "metrics/evaluate/clipscore" in path:
46
  return {"reference": "a photo of a cat", "candidate": "an image of a cute cat"}
 
47
  return {}
48
 
49
+ # Detect if endpoint expects query params
50
+ def use_query_params(path):
51
+ return "metrics/evaluate" in path # currently only metrics use query
52
+
53
+ # List of endpoints to test
54
+ ENDPOINTS = [
55
+ "/api/v1/audio/generate",
56
+ "/api/v1/video/generate",
57
+ "/api/v1/image/generate",
58
+ "/api/v1/ppt/generate",
59
+ "/api/v1/metrics/evaluate/bleu",
60
+ "/api/v1/metrics/evaluate/clipscore"
61
+ ]
62
+
63
+ for endpoint in ENDPOINTS:
64
+ url = f"{BASE_URL}{endpoint}"
65
+ payload = get_dummy_payload(endpoint)
66
+
67
+ print(f"\n=== Testing POST {url} ===")
68
+ print("Payload:", payload)
69
+
70
+ # Decide whether to use params or json
71
+ if use_query_params(endpoint):
72
+ response = requests.post(url, headers=headers, params=payload)
73
+ else:
74
+ response = requests.post(url, headers=headers, json=payload)
75
+
76
+ status = response.status_code
77
+ print("Status:", status)
78
+
79
+ if status == 200:
80
+ # Handle media files
81
+ content_type = response.headers.get("content-type", "")
82
+ if "application/json" in content_type:
83
+ print("JSON Response:", response.json())
84
+ else:
85
+ # Save binary file
86
+ ext = "bin"
87
+ if "image" in content_type:
88
+ ext = "png"
89
+ elif "audio" in content_type:
90
+ ext = "mp3"
91
+ elif "video" in content_type:
92
+ ext = "mp4"
93
+ elif "presentation" in content_type or "ppt" in endpoint:
94
+ ext = "pptx"
95
+
96
+ filename = unique_filename(endpoint.strip("/").replace("/", "_"), ext)
97
+ with open(filename, "wb") as f:
98
+ f.write(response.content)
99
+ print(f"βœ… Saved media file: {filename}")
100
+ else:
101
+ print("Error Response:", response.text)
102
+
103
+ time.sleep(1) # small delay to avoid spamming