pdf-ppt / app.py
asemxin2000's picture
Upload app.py with huggingface_hub
d3a1d98 verified
Raw
History Blame Contribute Delete
5.82 kB
import os
import sys
import tempfile
import gradio as gr
# Add backend directory to sys.path so internal imports work seamlessly
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'backend')))
from backend.pdf_processor import convert_pdf_to_images
from backend.services.export_service import ExportService
def process_pdf(pdf_file, mineru_api_base, mineru_token, baidu_api_key, baidu_secret_key, max_workers, progress=gr.Progress()):
if not pdf_file:
return None, "Error: No file uploaded."
if not mineru_token:
# Fallback to HF Secrets using exact screenshot names or defaults
mineru_token = os.environ.get("MinerU_Token", os.environ.get("MINERU_TOKEN", ""))
if not mineru_token:
return None, "Error: MinerU Token is required."
if not baidu_api_key:
baidu_api_key = os.environ.get("Baidu_API_Key", os.environ.get("BAIDU_API_KEY", ""))
if not baidu_secret_key:
baidu_secret_key = os.environ.get("Baidu_Secret_Key", os.environ.get("BAIDU_SECRET_KEY", ""))
if not mineru_api_base:
mineru_api_base = os.environ.get("MinerU_API_Base", os.environ.get("MINERU_API_BASE", "https://asemxin2000-mineru.hf.space"))
# Set up environment variables that the backend relies on
os.environ['MINERU_TOKEN'] = mineru_token
os.environ['MINERU_API_BASE'] = mineru_api_base
os.environ['BAIDU_API_KEY'] = baidu_api_key
os.environ['BAIDU_SECRET_KEY'] = baidu_secret_key
# We'll use a local temp upload folder
upload_dir = tempfile.mkdtemp()
os.environ['UPLOAD_FOLDER'] = upload_dir
try:
progress(0, desc="Converting PDF to images...")
# 1. Convert PDF to high-res images
image_paths = convert_pdf_to_images(pdf_file.name, output_dir=upload_dir, dpi=300)
if not image_paths:
return None, "Error: Failed to extract images from PDF."
progress(0.1, desc=f"Extracted {len(image_paths)} pages.")
# Progress callback adapter
def progress_adapter(step: str, message: str, percent: int):
# Gradio progress takes float [0, 1]
# Since pdf to image took 10%, we map the remaining 90% (percent / 100 * 0.9 + 0.1)
mapped_progress = (percent / 100.0) * 0.9 + 0.1
progress(mapped_progress, desc=f"[{step}] {message}")
# 2. Run the main PPTX conversion pipeline exactly as designed in banana-slides
# Defaulting export strategies to hybrid which combines MinerU and Baidu OCR
pptx_bytes, warnings = ExportService.create_editable_pptx_with_recursive_analysis(
image_paths=image_paths,
output_file=None, # Return bytes
slide_width_pixels=1920,
slide_height_pixels=1080,
max_depth=1, # Depth 1 is generally enough for presentations
max_workers=int(max_workers),
progress_callback=progress_adapter,
export_extractor_method='hybrid' if baidu_api_key else 'mineru',
export_inpaint_method='baidu' if baidu_api_key else 'generative', # generative requires AI model, let's just stick to baidu if we have it
fail_fast=False # tolerate warnings
)
if not pptx_bytes:
return None, "Error: PPTX generation returned empty bytes."
# Save to a temporary file
output_pptx_path = os.path.join(upload_dir, "output_presentation.pptx")
with open(output_pptx_path, "wb") as f:
f.write(pptx_bytes)
warning_msg = f"Done! {len(warnings.to_summary())} warnings encountered." if warnings.has_warnings() else "Done successfully!"
return output_pptx_path, warning_msg
except Exception as e:
import traceback
traceback.print_exc()
return None, f"An error occurred: {str(e)}"
# Define the Gradio Interface
with gr.Blocks(title="PDF to Editable PPTX") as demo:
gr.Markdown("# 🍌📄 PDF to Editable PPTX Converter")
gr.Markdown("Convert your PDF slides into high-fidelity editable PowerPoint files using OpenXLab MinerU and Baidu OCR APIs.")
with gr.Row():
with gr.Column(scale=1):
pdf_input = gr.File(label="Upload PDF", file_types=[".pdf"])
max_workers = gr.Slider(minimum=1, maximum=16, value=2, step=1, label="Max Workers (Parallel Processing)")
with gr.Accordion("API Keys (Optional if set in Space Secrets)", open=False):
mineru_api_base = gr.Textbox(label="MinerU API Base", value=os.environ.get("MinerU_API_Base", os.environ.get("MINERU_API_BASE", "https://asemxin2000-mineru.hf.space")), placeholder="https://asemxin2000-mineru.hf.space", info="MinerU 服务地址(HF Space 或 mineru.net)")
mineru_token = gr.Textbox(label="MinerU Token", type="password", value=os.environ.get("MinerU_Token", os.environ.get("MINERU_TOKEN", "")))
baidu_api_key = gr.Textbox(label="Baidu API Key", type="password", value=os.environ.get("Baidu_API_Key", os.environ.get("BAIDU_API_KEY", "")))
baidu_secret = gr.Textbox(label="Baidu Secret Key", type="password", value=os.environ.get("Baidu_Secret_Key", os.environ.get("BAIDU_SECRET_KEY", "")))
convert_btn = gr.Button("Convert to PPTX", variant="primary")
with gr.Column(scale=1):
status_box = gr.Textbox(label="Status", interactive=False)
pptx_output = gr.File(label="Download PPTX")
convert_btn.click(
fn=process_pdf,
inputs=[pdf_input, mineru_api_base, mineru_token, baidu_api_key, baidu_secret, max_workers],
outputs=[pptx_output, status_box]
)
if __name__ == "__main__":
demo.launch()