20260429_232813-fix: video frame display pipeline — default project seed, presigned URLs, Canvas/FrameTimeline real frames, upload-parse flow
This commit is contained in:
@@ -71,6 +71,24 @@ async def upload_media(
|
||||
logger.info("Linked upload to project_id=%s", project_id)
|
||||
else:
|
||||
logger.warning("Project id=%s not found for upload linkage", project_id)
|
||||
else:
|
||||
# Auto-create a project named after the file
|
||||
project = Project(
|
||||
name=file.filename,
|
||||
description="Auto-created from upload",
|
||||
status="pending",
|
||||
video_path=object_name,
|
||||
)
|
||||
db.add(project)
|
||||
db.commit()
|
||||
db.refresh(project)
|
||||
project_id = project.id
|
||||
object_name = f"uploads/{project_id}/{file.filename}"
|
||||
# Re-upload with corrected path
|
||||
upload_file(object_name, data, content_type=file.content_type or "application/octet-stream", length=len(data))
|
||||
project.video_path = object_name
|
||||
db.commit()
|
||||
logger.info("Auto-created project id=%s for upload %s", project_id, file.filename)
|
||||
|
||||
# TODO: enqueue async parsing job (Celery / background task)
|
||||
logger.info("Upload complete: %s (size=%d bytes). Async parsing queued.", object_name, len(data))
|
||||
@@ -79,6 +97,7 @@ async def upload_media(
|
||||
"object_name": object_name,
|
||||
"file_url": file_url,
|
||||
"size": len(data),
|
||||
"project_id": project_id,
|
||||
"message": "Upload successful. Parsing job queued.",
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from sqlalchemy.orm import Session
|
||||
from database import get_db
|
||||
from models import Project, Frame
|
||||
from schemas import ProjectCreate, ProjectOut, ProjectUpdate, FrameCreate, FrameOut
|
||||
from minio_client import get_presigned_url
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/api/projects", tags=["Projects"])
|
||||
@@ -40,7 +41,10 @@ def create_project(payload: ProjectCreate, db: Session = Depends(get_db)) -> Pro
|
||||
)
|
||||
def list_projects(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)) -> List[Project]:
|
||||
"""Retrieve a paginated list of projects."""
|
||||
return db.query(Project).offset(skip).limit(limit).all()
|
||||
projects = db.query(Project).offset(skip).limit(limit).all()
|
||||
for p in projects:
|
||||
p.frame_count = len(p.frames)
|
||||
return projects
|
||||
|
||||
|
||||
@router.get(
|
||||
@@ -53,6 +57,7 @@ def get_project(project_id: int, db: Session = Depends(get_db)) -> Project:
|
||||
project = db.query(Project).filter(Project.id == project_id).first()
|
||||
if not project:
|
||||
raise HTTPException(status_code=404, detail="Project not found")
|
||||
project.frame_count = len(project.frames)
|
||||
return project
|
||||
|
||||
|
||||
@@ -138,7 +143,7 @@ def list_frames(
|
||||
if not project:
|
||||
raise HTTPException(status_code=404, detail="Project not found")
|
||||
|
||||
return (
|
||||
frames = (
|
||||
db.query(Frame)
|
||||
.filter(Frame.project_id == project_id)
|
||||
.order_by(Frame.frame_index)
|
||||
@@ -146,6 +151,9 @@ def list_frames(
|
||||
.limit(limit)
|
||||
.all()
|
||||
)
|
||||
for frame in frames:
|
||||
frame.image_url = get_presigned_url(frame.image_url, expires=3600)
|
||||
return frames
|
||||
|
||||
|
||||
@router.get(
|
||||
|
||||
Reference in New Issue
Block a user