Turbiling's picture
Update app.py
f696cd8 verified
Raw
History Blame Contribute Delete
4.66 kB
import os
import uuid
import io
import shutil
import fitz # PyMuPDF
import gradio as gr
from pptx import Presentation
from pptx.util import Inches
from docx import Document
from docx.shared import Cm
from PIL import Image
# -------------------------
# Configuration
# -------------------------
UPLOAD_DIR = "uploads"
os.makedirs(UPLOAD_DIR, exist_ok=True)
MAX_FILE_SIZE_MB = 500
# -------------------------
# Core Conversion Logic
# -------------------------
def convert_pdf(file_path, target_format):
if file_path is None:
raise gr.Error("Please upload a PDF file.")
if not file_path.lower().endswith(".pdf"):
raise gr.Error("Only PDF files are supported.")
unique_id = str(uuid.uuid4())
pdf_path = os.path.join(UPLOAD_DIR, f"{unique_id}.pdf")
# ✅ FIX: copy file instead of file.read()
shutil.copy(file_path, pdf_path)
doc = fitz.open(pdf_path)
if len(doc) == 0:
doc.close()
os.remove(pdf_path)
raise gr.Error("The uploaded PDF is empty.")
# ---------- PDF → PPT ----------
if target_format == "PowerPoint (.pptx)":
output_path = os.path.join(UPLOAD_DIR, f"{unique_id}.pptx")
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
for page in doc:
pix = page.get_pixmap(matrix=fitz.Matrix(1.5, 1.5), alpha=False)
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
img_stream = io.BytesIO()
img.save(img_stream, format="JPEG", quality=80)
img_stream.seek(0)
slide = prs.slides.add_slide(prs.slide_layouts[6])
slide.shapes.add_picture(
img_stream, 0, 0,
width=prs.slide_width,
height=prs.slide_height
)
img_stream.close()
prs.save(output_path)
# ---------- PDF → Word ----------
else:
output_path = os.path.join(UPLOAD_DIR, f"{unique_id}.docx")
word_doc = Document()
for section in word_doc.sections:
section.top_margin = Cm(0.5)
section.bottom_margin = Cm(0.5)
section.left_margin = Cm(0.5)
section.right_margin = Cm(0.5)
for i, page in enumerate(doc):
pix = page.get_pixmap(matrix=fitz.Matrix(1.5, 1.5), alpha=False)
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
img_stream = io.BytesIO()
img.save(img_stream, format="JPEG", quality=80)
img_stream.seek(0)
word_doc.add_picture(img_stream, width=Cm(20))
if i < len(doc) - 1:
word_doc.add_page_break()
img_stream.close()
word_doc.save(output_path)
doc.close()
os.remove(pdf_path)
return output_path
# -------------------------
# Utility: Clear Files
# -------------------------
def clear_files():
for f in os.listdir(UPLOAD_DIR):
try:
os.remove(os.path.join(UPLOAD_DIR, f))
except:
pass
return None
# -------------------------
# Gradio UI
# -------------------------
with gr.Blocks(title="PDF Converter | Developer: Najaf Ali Sharqi") as demo:
gr.Markdown("""
# 📄 PDF Conversion Tool
**Developer:** Najaf Ali Sharqi
Convert PDF files generated by NotebookLM into **editable PowerPoint or Word documents**
without modifying original content, layout, or images.
""")
with gr.Row():
pdf_input = gr.File(
label="Upload PDF File",
file_types=[".pdf"]
)
format_choice = gr.Radio(
choices=["PowerPoint (.pptx)", "Word Document (.docx)"],
value="PowerPoint (.pptx)",
label="Select Output Format"
)
with gr.Row():
convert_btn = gr.Button("Convert")
clear_btn = gr.Button("Clear Uploaded Files")
output_file = gr.File(label="Download Converted File")
convert_btn.click(
fn=convert_pdf,
inputs=[pdf_input, format_choice],
outputs=output_file
)
clear_btn.click(
fn=clear_files,
outputs=output_file
)
gr.Markdown("""
---
⚠️ **Important Notes**
- UI instructions are provided in English only
- The tool does **not** add, remove, or modify content
- Output files preserve original visuals exactly
- Designed for Hugging Face deployment using Gradio
""")
# -------------------------
# Launch (HF Compatible)
# -------------------------
demo.launch(
server_name="0.0.0.0",
server_port=7860,
ssr_mode=False
)