from PIL import Image, ImageDraw, ImageFont import cv2 import numpy as np import textwrap def generate_lyric_frame(lyric, image_size): # If image_size is None, provide a default value if image_size is None: image_size = (800, 600) # Example default size, you can change this # Ensure image_size is a tuple image_size = tuple(image_size) image = Image.new('RGB', image_size, color='black') draw = ImageDraw.Draw(image) # Use PIL's default font font = ImageFont.load_default() # Wrap text max_width = image_size[0] - 40 # Keeping 20 pixels margin on each side wrapped_text = textwrap.fill(lyric, width=40) lines = wrapped_text.split('\n') # Calculate text width and height text_width = max(draw.textlength(line, font=font) for line in lines) # Corrected line here text_height = sum([font.getmask(line).getbbox()[3] for line in lines if font.getmask(line).getbbox()]) # Corrected line here # Calculate starting coordinates to center the text block text_x = (image_size[0] - text_width) / 2 text_y = (image_size[1] - text_height) / 2 # Draw the wrapped text on the image y = text_y for line in lines: draw.text((text_x, y), line, font=font, fill='white') y += font.getmask(line).getbbox()[3] if font.getmask(line).getbbox() else 0 # Corrected line here return image def generate_video(lyrics_with_timing, image_size=(800, 600), frame_rate=30): frames = [] for start_time, end_time, lyric in lyrics_with_timing: # Calculate the number of frames for this lyric segment num_frames = int((end_time - start_time) * frame_rate) # Create frames with the lyric text for _ in range(num_frames): frame = generate_lyric_frame(lyric, image_size) frames.append(frame) # Combine frames into a video video = combine_frames_into_video(frames, frame_rate) return video def combine_frames_into_video(frames, frame_rate): # Convert the first frame to a NumPy array to get its shape first_frame_np = np.array(frames[0]) height, width, _ = first_frame_np.shape # Define the codec and create a video writer object fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('output.avi', fourcc, frame_rate, (width, height)) # Write each frame to the video file for frame in frames: # Convert PIL image to NumPy array frame_np = np.array(frame) # Convert RGB to BGR as OpenCV uses BGR format frame_bgr = cv2.cvtColor(frame_np, cv2.COLOR_RGB2BGR) # Write the BGR frame to the video out.write(frame_bgr) # Release the video writer object out.release() return 'output.avi'