odyssey-backend / app.py
Fraser's picture
Initial backend setup with Gradio
fec820d
raw
history blame
3.83 kB
# app.py - Odyssey Backend (Gradio)
import os
import uuid
import json
from pathlib import Path
from typing import Tuple
import gradio as gr
from huggingface_hub import HfApi
# ===== Config =====
REPO_ID = "Fraser/odyssey-videos" # dataset to write to
TOKEN = os.environ.get("HF_TOKEN") # set in Space Secrets
if not TOKEN:
raise RuntimeError("Missing HF_TOKEN secret")
STAGING = Path("/tmp/staging")
STAGING.mkdir(parents=True, exist_ok=True)
api = HfApi(token=TOKEN)
def _public_url(uuid_str: str) -> str:
"""Build the public resolve URL for dataset files"""
return f"https://huggingface.co/datasets/{REPO_ID}/resolve/main/{uuid_str}.mp4"
def upload_video(video_file) -> Tuple[str, str]:
"""
Upload a video file to the Fraser/odyssey-videos dataset
Args:
video_file: Video file (mp4)
Returns:
JSON string with: {"uuid": "...", "url": "...", "share": "..."}
"""
if video_file is None:
return json.dumps({"error": "No video file provided"}), ""
try:
# Generate UUID
uid = str(uuid.uuid4())
# Get the uploaded file path
video_path = Path(video_file)
# Upload to HuggingFace dataset
api.upload_file(
path_or_fileobj=str(video_path),
path_in_repo=f"{uid}.mp4",
repo_id=REPO_ID,
repo_type="dataset",
commit_message=f"Add video {uid}.mp4",
)
# Build response
url = _public_url(uid)
result = {
"uuid": uid,
"url": url,
"share": f"https://fraser-odyssey.static.hf.space/?id={uid}"
}
return json.dumps(result), url
except Exception as e:
return json.dumps({"error": str(e)}), ""
def get_video_url(uuid_str: str) -> str:
"""Get the public URL for a video by UUID"""
if not uuid_str:
return ""
return _public_url(uuid_str)
# ===== Gradio Interface =====
with gr.Blocks(title="Odyssey Video Backend") as demo:
gr.Markdown("""
# 🎬 Odyssey Video Backend
Backend service for uploading Odyssey adventure videos to HuggingFace datasets.
This Space is primarily accessed programmatically by the [Odyssey frontend](https://huggingface.co/spaces/Fraser/odyssey-frontend).
""")
with gr.Tab("Upload Video"):
gr.Markdown("### Upload a video to the odyssey-videos dataset")
video_input = gr.Video(label="Video File (MP4)")
upload_btn = gr.Button("Upload to Dataset", variant="primary")
result_json = gr.Textbox(label="Result (JSON)", lines=5)
result_url = gr.Textbox(label="Video URL", interactive=False)
upload_btn.click(
fn=upload_video,
inputs=[video_input],
outputs=[result_json, result_url]
)
with gr.Tab("Get Video URL"):
gr.Markdown("### Get public URL for a video by UUID")
uuid_input = gr.Textbox(label="Video UUID", placeholder="Enter UUID...")
get_url_btn = gr.Button("Get URL")
url_output = gr.Textbox(label="Video URL", interactive=False)
get_url_btn.click(
fn=get_video_url,
inputs=[uuid_input],
outputs=[url_output]
)
gr.Markdown("""
---
## API Usage
### JavaScript/TypeScript
```javascript
import { Client } from "@gradio/client";
const client = await Client.connect("Fraser/odyssey-backend");
// Upload video
const result = await client.predict("/upload_video", {
video_file: blob // or file handle
});
```
### Python
```python
from gradio_client import Client
client = Client("Fraser/odyssey-backend")
result = client.predict("/upload_video", video_file="path/to/video.mp4")
```
""")
if __name__ == "__main__":
demo.launch()