Mbonea commited on
Commit
2430e21
0 Parent(s):

initial commit

Browse files
Files changed (4) hide show
  1. Dockerfile +37 -0
  2. README.md +8 -0
  3. main.py +147 -0
  4. requirements.txt +6 -0
Dockerfile ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM tiangolo/uvicorn-gunicorn-fastapi:python3.10
2
+
3
+ RUN apt-get update && apt-get install -y \
4
+ ffmpeg \
5
+ libgl1-mesa-dev \
6
+ libgles2-mesa-dev \
7
+ libglu1-mesa-dev \
8
+ build-essential \
9
+ cmake \
10
+ freeglut3-dev \
11
+ libglfw3-dev \
12
+ libglew-dev \
13
+ libsdl2-dev \
14
+ libjpeg-dev \
15
+ libpng-dev \
16
+ libfreetype6-dev \
17
+ mesa-utils \
18
+ libgl1-mesa-dri \
19
+ libgl1-mesa-glx \
20
+ curl \
21
+ python3-dev \
22
+ libpq-dev \
23
+ libasound2-dev \
24
+ portaudio19-dev \
25
+ && rm -rf /var/lib/apt/lists/*
26
+
27
+ COPY requirements.txt .
28
+ RUN pip install --no-cache-dir -r requirements.txt
29
+
30
+ COPY . /app
31
+ WORKDIR /app
32
+
33
+ # Download and install the depthflow binary
34
+ RUN curl -L -o /usr/local/bin/depthflow https://github.com/BrokenSource/DepthFlow/releases/latest/download/depthflow-cpu-linux-amd64-latest.bin
35
+ RUN chmod +x /usr/local/bin/depthflow
36
+
37
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
README.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: DeepFlow
3
+ emoji: 🌊
4
+ colorFrom: purple
5
+ colorTo: gray
6
+ sdk: docker
7
+ app_port: 8000
8
+ ---
main.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import tempfile
3
+ import requests
4
+ from mimetypes import guess_extension
5
+ from PIL import Image
6
+ from io import BytesIO
7
+ import subprocess
8
+ from fastapi import FastAPI, UploadFile, File, HTTPException, Response, Request
9
+ from typing import List, Optional
10
+ import asyncio, aiofiles
11
+ from fastapi.responses import StreamingResponse, FileResponse
12
+
13
+ app = FastAPI()
14
+
15
+
16
+ def download_image(image_url: str):
17
+ # Create a temporary directory
18
+ temp_dir = tempfile.mkdtemp()
19
+
20
+ # Get the image content
21
+ response = requests.get(image_url)
22
+ response.raise_for_status()
23
+
24
+ # Detect the image type
25
+ image = Image.open(BytesIO(response.content))
26
+ image_format = image.format.lower()
27
+ image_extension = guess_extension(f"image/{image_format}")
28
+
29
+ if image_extension is None:
30
+ raise ValueError("Cannot detect image file type.")
31
+
32
+ # Define the image file path
33
+ image_path = os.path.join(temp_dir, f"image{image_extension}")
34
+
35
+ # Save the image file
36
+ with open(image_path, "wb") as image_file:
37
+ image_file.write(response.content)
38
+
39
+ # Return the image path and dimensions
40
+ return image_path, image.size
41
+
42
+
43
+ def make_effect(
44
+ image_link: str,
45
+ filename: str,
46
+ frame_rate: int,
47
+ duration: int,
48
+ quality: int,
49
+ ssaa: float,
50
+ raw: bool,
51
+ ):
52
+ # Download the image and get its dimensions
53
+ image_path, (width, height) = download_image(image_url=image_link)
54
+ print(f"Image path: {image_path}, Width: {width}, Height: {height}", "#" * 100)
55
+
56
+ # Define the output video file path
57
+ destination = os.path.join("/tmp/Video", filename)
58
+
59
+ # Create the destination directory if it doesn't exist
60
+ os.makedirs(os.path.dirname(destination), exist_ok=True)
61
+
62
+ # Build the depthflow command
63
+ command = [
64
+ "depthflow",
65
+ "input",
66
+ "-i",
67
+ image_path,
68
+ "main",
69
+ "-f",
70
+ str(frame_rate),
71
+ "-t",
72
+ str(duration),
73
+ "--width",
74
+ str(width),
75
+ "--height",
76
+ str(height),
77
+ "--quality",
78
+ str(quality),
79
+ "--ssaa",
80
+ str(ssaa),
81
+ "--benchmark",
82
+ ]
83
+
84
+ if raw:
85
+ command.append("--raw")
86
+
87
+ command.extend(["--output", destination])
88
+
89
+ # Execute the depthflow command
90
+ subprocess.run(command, check=True)
91
+
92
+ return destination
93
+
94
+
95
+ @app.post("/generate_video")
96
+ async def generate_video(
97
+ image_link: str = UploadFile(File(...), alias="image_link"),
98
+ filename: str = "output.mp4",
99
+ frame_rate: int = 30,
100
+ duration: int = 3,
101
+ quality: int = 10,
102
+ ssaa: float = 0.75,
103
+ raw: bool = True,
104
+ ):
105
+ try:
106
+ output_path = await make_effect(
107
+ image_link, filename, frame_rate, duration, quality, ssaa, raw
108
+ )
109
+ return {"output_file": filename}
110
+ except Exception as e:
111
+ raise HTTPException(status_code=400, detail=str(e))
112
+
113
+
114
+ @app.get("/download/{filename}")
115
+ async def download_video(filename: str, request: Request):
116
+ video_directory = "/tmp/Video"
117
+ video_path = os.path.join(video_directory, filename)
118
+ if not os.path.isfile(video_path):
119
+ raise HTTPException(status_code=404, detail="Video not found")
120
+
121
+ range_header = request.headers.get("Range", None)
122
+ video_size = os.path.getsize(video_path)
123
+
124
+ if range_header:
125
+ start, end = range_header.strip().split("=")[1].split("-")
126
+ start = int(start)
127
+ end = video_size if end == "" else int(end)
128
+
129
+ headers = {
130
+ "Content-Range": f"bytes {start}-{end}/{video_size}",
131
+ "Accept-Ranges": "bytes",
132
+ }
133
+
134
+ content = read_file_range(video_path, start, end)
135
+ return StreamingResponse(content, media_type="video/mp4", headers=headers)
136
+
137
+ return FileResponse(video_path, media_type="video/mp4")
138
+
139
+
140
+ async def read_file_range(path, start, end):
141
+ async with aiofiles.open(path, "rb") as file:
142
+ await file.seek(start)
143
+ while True:
144
+ data = await file.read(1024 * 1024) # read in chunks of 1MB
145
+ if not data or await file.tell() > end:
146
+ break
147
+ yield data
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ fastapi
2
+ pydantic
3
+ requests
4
+ Pillow
5
+ numpy
6
+ aiofiles