fomext commited on
Commit
3b8ad4d
·
verified ·
1 Parent(s): 65baf95

Upload 6 files

Browse files
Files changed (6) hide show
  1. Dockerfile +30 -0
  2. app.py +30 -0
  3. image/qr.py +6 -0
  4. image/renderer.py +12 -0
  5. image/watermark.py +21 -0
  6. requirements.txt +7 -0
Dockerfile ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10
2
+
3
+ # Install system dependencies
4
+ RUN apt-get update && apt-get install -y \
5
+ ffmpeg \
6
+ libgl1 \
7
+ libglib2.0-0 \
8
+ && rm -rf /var/lib/apt/lists/*
9
+
10
+ # Create non-root user (HF best practice)
11
+ RUN useradd -m -u 1000 user
12
+ USER user
13
+
14
+ ENV PATH=/home/user/.local/bin:$PATH
15
+ WORKDIR /app
16
+
17
+ # Copy requirements first (better caching)
18
+ COPY --chown=user requirements.txt .
19
+
20
+ RUN pip install --no-cache-dir --upgrade pip \
21
+ && pip install --no-cache-dir -r requirements.txt
22
+
23
+ # Copy project files
24
+ COPY --chown=user . .
25
+
26
+ # HuggingFace expects port 7860
27
+ EXPOSE 7860
28
+
29
+ # IMPORTANT: start FastAPI properly
30
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, UploadFile, Form
2
+ from fastapi.responses import FileResponse
3
+ import os, shutil
4
+
5
+ from image.qr import generate_qr
6
+ from image.watermark import add_qr_to_background
7
+
8
+ app = FastAPI()
9
+
10
+ TEMP_DIR = "temp"
11
+ os.makedirs(TEMP_DIR, exist_ok=True)
12
+
13
+ @app.post("/background")
14
+ async def create_background(
15
+ file: UploadFile,
16
+ premium: bool = Form(False)
17
+ ):
18
+ input_path = f"{TEMP_DIR}/input.png"
19
+ output_path = f"{TEMP_DIR}/output.png"
20
+
21
+ with open(input_path, "wb") as f:
22
+ f.write(await file.read())
23
+
24
+ if premium:
25
+ shutil.copy(input_path, output_path)
26
+ else:
27
+ qr = generate_qr("https://cloudfom.org")
28
+ add_qr_to_background(input_path, output_path, qr)
29
+
30
+ return FileResponse(output_path, media_type="image/png")
image/qr.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import qrcode
2
+
3
+ def generate_qr(url: str):
4
+ qr = qrcode.make(url)
5
+ qr = qr.resize((120, 120))
6
+ return qr
image/renderer.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from moviepy.editor import ImageSequenceClip
2
+ import os
3
+
4
+ def render_video(frames_dir, output_path, fps=30):
5
+ frames = sorted([
6
+ os.path.join(frames_dir, f)
7
+ for f in os.listdir(frames_dir)
8
+ if f.endswith(".png")
9
+ ])
10
+
11
+ clip = ImageSequenceClip(frames, fps=fps)
12
+ clip.write_videofile(output_path, codec="libx264")
image/watermark.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image, ImageDraw, ImageFont
2
+
3
+ def add_qr_to_background(img_path, output_path, qr_img):
4
+ img = Image.open(img_path).convert("RGBA")
5
+
6
+ qr_x = img.width - qr_img.width - 24
7
+ qr_y = img.height - qr_img.height - 48
8
+
9
+ img.paste(qr_img, (qr_x, qr_y), qr_img)
10
+
11
+ draw = ImageDraw.Draw(img)
12
+ font = ImageFont.load_default()
13
+
14
+ draw.text(
15
+ (qr_x, qr_y + qr_img.height + 6),
16
+ "Lyric Video Maker",
17
+ fill=(255, 255, 255, 180),
18
+ font=font
19
+ )
20
+
21
+ img.save(output_path)
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ pillow
4
+ qrcode
5
+ moviepy
6
+ opencv-python-headless
7
+ python-multipart