Video2Poster_Agent / utils.py
wangjin2000's picture
Upload utils.py
afefb95 verified
# -*- coding: utf-8 -*-
# Use ReportLab package to create PDF poster
from reportlab.pdfbase import pdfmetrics
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import cm
from reportlab.platypus import (
SimpleDocTemplate,
Paragraph,
Spacer,
Table,
TableStyle,
Image,
Flowable,
ListFlowable,
ListItem,
)
from reportlab.lib import colors
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
import yt_dlp
import cv2
from PIL import Image as PILImage
import os
import tempfile
import re
import uuid
import pymupdf
'''
# UnicodeCIDfont names
$chs$ = Chinese Simplified (mainland): '$STSong-Light$'
$cht$ = Chinese Traditional (Taiwan): '$MSung-Light$', '$MHei-Medium$'
$kor$ = Korean: '$HYSMyeongJoStd-Medium$','$HYGothic-Medium$'
$jpn$ = Japanese: '$HeiseiMin-W3$', '$HeiseiKakuGo-W5$'
'''
# Configuration
# Register the Chinese font with Reportlab
pdfmetrics.registerFont(UnicodeCIDFont('STSong-Light'))
pdfmetrics.registerFont(UnicodeCIDFont('MSung-Light'))
PAGE_SIZE = A4
MARGIN = 1.0 * cm
COLUMNS = 3 # Now using 3 columns
STYLE = getSampleStyleSheet()
style_body = STYLE["BodyText"]
style_title = STYLE['Title']
style_title.alignment = 1 # center the title
# Calculate available width for tables
page_width = PAGE_SIZE[0] - 2*MARGIN
col_width = page_width / COLUMNS
img_width = col_width - 1*cm # Leave some padding
img_height = 5*cm
#==========================================================================
def create_poster(filename, images, lang, summary, url = None):
print("Output language is:", lang)
#generate PDF file
doc = SimpleDocTemplate(filename, pagesize=PAGE_SIZE,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=MARGIN, bottomMargin=MARGIN)
story = []
# Define a style with the detected language font
if lang.lower() == 'chinese':
style_body.fontName = 'STSong-Light'
style_title.fontName = 'STSong-Light'
else:
style_body.fontName = 'Helvetica'
style_title.fontName = 'Helvetica-Bold'
# Create table data for detected images
table_data = []
list_content = []
with tempfile.TemporaryDirectory() as temp_dir:
# Process output summary
question = []
current_answer = []
answers_part = summary.strip().split("\n")
title_text = "Summary" # initialize title
title = Paragraph(f"<b>{title_text}</b>", style_title)
for line in answers_part: #.split("\n"):
if re.search("0.", line): #title line
clean_line = line.replace("*", "")
title_text = clean_line.split("0.")
if len(title_text) > 1:
title_text = title_text[1]
else:
title_text = title_text[0]
index = title_text.find(':')
if index != -1:
title_text = title_text[index+1:]
title = Paragraph(f"<b>{title_text}</b>", style_title)
elif re.search(r'\d\.', line):
# Start of a new question-answer section
list_content.append(Spacer(1, 0.3*cm))
if current_answer:
list_item = Paragraph(f"<b>{current_answer}</b>", style_body),
list_content.append(list_item)
current_answer = []
line_content = line.replace("*", "").split(":")
question = str(line_content[0])
question = Paragraph(f"<b>{question}</b>", style_body)
list_content.append(question)
if len(line_content) > 1: #handle same line answer
list_item = Paragraph(f"<b>{line_content[1]}</b>", style_body)
list_content.append(list_item)
elif line.strip() and question:
list_item = Paragraph(f"<b>{line}</b>", style_body)
list_content.append(list_item)
#add last section
if current_answer:
list_item = Paragraph(f"<b>{line}</b>", style_body)
list_content.append(list_item)
# construct the full list
markdown_output = ListFlowable(list_content,
bulletType='bullet',
bulletColor='white', value='circle'
),
output_list = markdown_output[0] #workaround for converting tuple to list
# Insert images into a table
row_cells = []
for id, image in enumerate(images):
face_filename = f'{id}.jpg'
image_path = os.path.join(temp_dir, face_filename)
cv2.imwrite(image_path, image)
# Load the image back into memory because Image object needs filepath input
pil_img = PILImage.open(image_path)
# Create cell content
cell_content = [
Spacer(1, 0.3*cm),
Image(image_path, width=img_width, height=img_height),
Spacer(1, 0.3*cm),
]
row_cells.append(cell_content)
# Add row to table
table_data.append(row_cells)
# Create table with styling
tbl = Table(table_data,
colWidths=[col_width]*COLUMNS,
rowHeights=img_height+0.5*cm)
tbl.setStyle(TableStyle([
('ALIGN', (0,0), (-1,-1), 'CENTER'),
('VALIGN', (0,0), (-1,-1), 'CENTER'),
('PADDING', (0,0), (-1,-1), 10),
('BOX', (0,0), (-1,-1), 0.5, colors.white),
('INNERGRID', (0,0), (-1,-1), 0.5, colors.white),
]))
# add flowables
story.append(title)
story.append(tbl)
story.append(Spacer(1,0.3*cm))
story.append(output_list)
story.append(Spacer(1,0.5*cm))
# Clickable video link
if url:
link_text = f'<link href="{url}"><font color="{colors.blue}"><u>View Original Video</u></font></link>'
link_paragraph = Paragraph(link_text, style_body)
story.append(link_paragraph)
# build a page
doc.build(story)
return filename
def generate_unique_filename(extension):
return f"{uuid.uuid4()}{extension}"
def generate_tmp_filename(basename, extension):
return f"{basename}{extension}"
def pdf_to_jpg(pdf_path, output_path):
doc = pymupdf.open(pdf_path)
page = doc.load_page(0)
pix = page.get_pixmap()
pix.save(output_path, "JPEG")
image = PILImage.open(output_path)
doc.close()
return image, output_path
def download_youtube_video(url):
"""Downloads a Youtube video using yt-dlp."""
basename = os.path.basename(url)
output_path = generate_tmp_filename(basename, ".mp4")
ydl_opts = {
'outtmpl': output_path, # Path where the video will be saved
'format': 'best', # Download the best quality available
'cookiefile': 'cookies.txt', # Path to your cookies file #JW 20250115
}
try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
return output_path
except Exception as e:
print("load yt_dlp:", e)
return str(e)