Atualmente, o script exibe apenas um verso por vez. Gostaria que o script fosse modificado para mostrar três versos simultaneamente: o verso anterior, o verso atual e o verso seguinte. O verso atual deve ser exibido no centro, com o verso anterior acima dele e o verso seguinte abaixo.

É importante que sejam mostradas três frases completas na tela, e não apenas três palavras.

Por favor,  após ter pensado a fundo passo a passo, envie o código completo com as atualizações necessárias.

```python
import re
from datetime import timedelta
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import subprocess
import os
import multiprocessing
from functools import lru_cache
import shutil
from tqdm import tqdm
import time

# Configurações
IMAGE_SIZE = (1920, 1080)
FONT_COLOR = "#FBF04A"
HIGHLIGHT_COLOR = "#FF6156"
OUTLINE_COLOR = "#000000"
UPPER_CASE = False
FPS = 10
FADE_DURATION = 3
FONT_SIZE_INCOMPLETE = 65
FONT_SIZE_COMPLETE = 65
POSICAO = 1  # 1: centralizado, 2: parte inferior, 3: parte superior
FONT_PATH = r"C:\Users\lucas\Downloads\LilitaOne-Regular.ttf"


def hex_to_rgb(hex_color):
    return tuple(int(hex_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))


def parse_time(time_str):
    match = re.match(r'(\d+):(\d+):(\d+)', time_str)
    if match:
        minutes, seconds, milliseconds = map(int, match.groups())
        return timedelta(minutes=minutes, seconds=seconds, milliseconds=milliseconds)
    return timedelta(0)


def get_audio_duration(audio_file):
    command = [
        'ffprobe',
        '-v', 'error',
        '-show_entries', 'format=duration',
        '-of', 'default=noprint_wrappers=1:nokey=1',
        audio_file
    ]
    result = subprocess.run(command, capture_output=True, text=True)
    return float(result.stdout)


def read_subtitles(filename):
    subtitles = []
    with open(filename, 'r', encoding='utf-8') as file:
        for line in file:
            match = re.match(r'\[(\d+:\d+:\d+)\] (.+)', line.strip())
            if match:
                time_str, word = match.groups()
                subtitles.append((parse_time(time_str), word.upper() if UPPER_CASE else word))
    
    audio_duration = get_audio_duration('audio.wav')
    final_timestamp = timedelta(seconds=audio_duration)
    subtitles.append((final_timestamp, ""))
    
    return subtitles


@lru_cache(maxsize=1000)
def create_gradient_word(word, width, height, start_color, end_color, progress, font_size):
    font = ImageFont.truetype(FONT_PATH, font_size)
    ascent, descent = font.getmetrics()
    total_height = ascent + descent

    padding = 20
    word_image = Image.new('RGBA', (int(width) + padding, total_height + padding), (0, 0, 0, 0))
    draw = ImageDraw.Draw(word_image)
    
    x, y = padding // 2, ascent

    # Desenhar o texto principal sem sombra
    draw.text((x, y), word, font=font, fill=hex_to_rgb(end_color), anchor="ls")
    
    mask = Image.new('L', word_image.size, 0)
    mask_draw = ImageDraw.Draw(mask)
    mask_draw.text((x, y), word, font=font, fill=255, anchor="ls")
    mask = mask.filter(ImageFilter.GaussianBlur(radius=1.0))
    
    gradient = Image.new('RGBA', word_image.size, (0, 0, 0, 0))
    start_color_rgb = hex_to_rgb(start_color)
    end_color_rgb = hex_to_rgb(end_color)
    
    for x_coord in range(word_image.width):
        ratio = max(0, min(1, (x_coord / (width + padding) - progress) / 0.1))
        r = int(start_color_rgb[0] + (end_color_rgb[0] - start_color_rgb[0]) * ratio)
        g = int(start_color_rgb[1] + (end_color_rgb[1] - start_color_rgb[1]) * ratio)
        b = int(start_color_rgb[2] + (end_color_rgb[2] - start_color_rgb[2]) * ratio)
        color = (r, g, b, 255)
        ImageDraw.Draw(gradient).line([(x_coord, 0), (x_coord, word_image.height)], fill=color)
    
    gradient.putalpha(mask)
    
    return Image.alpha_composite(word_image, gradient)


def process_frame(frame_index, subtitles, background_image, num_frames):
    current_time = timedelta(seconds=frame_index / FPS)
    image = background_image.copy()

    # Processar e desenhar o texto
    draw = ImageDraw.Draw(image)
    words = [word for _, word in subtitles]
    current_word_index = next((i for i, (word_time, _) in enumerate(subtitles) if word_time > current_time), len(subtitles) - 1)
    current_word_index = max(0, current_word_index - 1)

    start_index = current_word_index
    while start_index > 0 and not words[start_index - 1].endswith('.'):
        start_index -= 1

    end_index = next((i for i in range(start_index, len(words)) if words[i].endswith('.')), len(words))
    end_index = min(end_index + 1, len(words))

    is_complete_sentence = words[start_index][0].isupper() and words[end_index - 1].endswith('.')

    current_font_size = FONT_SIZE_COMPLETE if is_complete_sentence else FONT_SIZE_INCOMPLETE
    font = ImageFont.truetype(FONT_PATH, current_font_size)
    space_width = font.getlength(' ')
    word_widths = [font.getlength(word) for word in words]

    max_words_per_line = 4
    num_lines = 4
    line_spacing = 10
    max_width = IMAGE_SIZE[0] - 40

    if is_complete_sentence:
        sentence_words = words[start_index:end_index]
        sentence_widths = word_widths[start_index:end_index]
        
        lines = []
        current_line = []
        current_line_width = 0
        for word, width in zip(sentence_words, sentence_widths):
            if current_line_width + width + space_width > max_width and current_line:
                lines.append(current_line)
                current_line = []
                current_line_width = 0
            current_line.append(word)
            current_line_width += width + space_width
        if current_line:
            lines.append(current_line)
        
        total_height = len(lines) * current_font_size + (len(lines) - 1) * line_spacing

        if POSICAO == 1:  # Centralizado
            y = (IMAGE_SIZE[1] - total_height) // 2
        elif POSICAO == 2:  # Parte inferior
            y = IMAGE_SIZE[1] - total_height - 50
        else:  # Parte superior
            y = 50

        word_index = start_index
        for line in lines:
            line_widths = [font.getlength(word) for word in line]
            total_width = sum(line_widths) + space_width * (len(line) - 1)
            start_x = (IMAGE_SIZE[0] - total_width) // 2
            x = start_x

            for word in line:
                word_time = subtitles[word_index][0]
                
                next_word_time = subtitles[word_index + 1][0] if word_index + 1 < len(subtitles) else word_time + timedelta(seconds=2)

                ascent_word, descent_word = font.getmetrics()
                text_width = font.getlength(word)
                y_centered = y + ascent_word

                if current_time >= next_word_time:
                    color = FONT_COLOR
                    progress = 1.0
                elif current_time >= word_time:
                    word_duration = (next_word_time - word_time).total_seconds()
                    progress = min(max((current_time - word_time).total_seconds() / word_duration, 0.0), 1.0)
                    color = FONT_COLOR
                else:
                    color = HIGHLIGHT_COLOR
                    progress = 1.0

                gradient_image = create_gradient_word(word, text_width, current_font_size, color, HIGHLIGHT_COLOR, progress, current_font_size)
                image.paste(gradient_image, (int(x - 5), int(y_centered - ascent_word - 5)), gradient_image)

                x += text_width + space_width
                word_index += 1

            y += current_font_size + line_spacing
    else:
        start_index = (current_word_index // (max_words_per_line * num_lines)) * (max_words_per_line * num_lines)
        total_height = num_lines * current_font_size + (num_lines - 1) * line_spacing

        if POSICAO == 1:  # Centralizado
            y = (IMAGE_SIZE[1] - total_height) // 2
        elif POSICAO == 2:  # Parte inferior
            y = IMAGE_SIZE[1] - total_height - 50
        else:  # Parte superior
            y = 50

        word_pos = start_index

        for line in range(num_lines):
            line_start = start_index + line * max_words_per_line
            line_end = min(line_start + max_words_per_line, len(words))
            line_words = words[line_start:line_end]
            line_widths = word_widths[line_start:line_end]
            
            total_width = sum(line_widths) + space_width * (len(line_words) - 1)
            start_x = (IMAGE_SIZE[0] - total_width) // 2
            x = start_x

            for word in line_words:
                word_index = word_pos
                word_time = subtitles[word_index][0]
                
                next_word_time = subtitles[word_index + 1][0] if word_index + 1 < len(subtitles) else word_time + timedelta(seconds=2)

                ascent_word, descent_word = font.getmetrics()
                text_width = font.getlength(word)
                y_centered = y + ascent_word

                if current_time >= next_word_time:
                    color = FONT_COLOR
                    progress = 1.0
                elif current_time >= word_time:
                    word_duration = (next_word_time - word_time).total_seconds()
                    progress = min(max((current_time - word_time).total_seconds() / word_duration, 0.0), 1.0)
                    color = FONT_COLOR
                else:
                    color = HIGHLIGHT_COLOR
                    progress = 1.0

                gradient_image = create_gradient_word(word, text_width, current_font_size, color, HIGHLIGHT_COLOR, progress, current_font_size)
                image.paste(gradient_image, (int(x - 5), int(y_centered - ascent_word - 5)), gradient_image)

                x += text_width + space_width
                word_pos += 1

            y += current_font_size + line_spacing

    # Aplicar fade in e fade out
    if frame_index < FADE_DURATION * FPS:
        fade_opacity = frame_index / (FADE_DURATION * FPS)
        fade_overlay = Image.new('RGBA', image.size, (0, 0, 0, int(255 * (1 - fade_opacity))))
        image = Image.alpha_composite(image.convert('RGBA'), fade_overlay).convert('RGB')
    elif frame_index > num_frames - FADE_DURATION * FPS:
        fade_opacity = (num_frames - frame_index) / (FADE_DURATION * FPS)
        fade_overlay = Image.new('RGBA', image.size, (0, 0, 0, int(255 * (1 - fade_opacity))))
        image = Image.alpha_composite(image.convert('RGBA'), fade_overlay).convert('RGB')

    # Converter para RGB para salvar como JPEG
    return image.convert('RGB')


def generate_frames_chunk(args):
    start_frame, end_frame, subtitles, output_dir, background_image, num_frames, progress_queue = args

    for frame_index in range(start_frame, end_frame):
        try:
            image = process_frame(frame_index, subtitles, background_image, num_frames)
            frame_filename = os.path.join(output_dir, f"frame_{frame_index:04d}.jpg")
            image.save(frame_filename, quality=95)
            progress_queue.put(1)
        except Exception as e:
            print(f"Erro ao processar o frame {frame_index}: {str(e)}")
            progress_queue.put(1)  # Ainda incrementamos o progresso para evitar travamentos

    return end_frame - start_frame


def generate_frames_parallel(subtitles, output_dir, background_image):
    total_duration = (subtitles[-1][0] + timedelta(seconds=2)).total_seconds()
    num_frames = int(total_duration * FPS) + 1

    num_processes = multiprocessing.cpu_count()
    chunk_size = num_frames // num_processes + 1

    manager = multiprocessing.Manager()
    progress_queue = manager.Queue()

    args_list = [
        (i * chunk_size, min((i + 1) * chunk_size, num_frames), subtitles, output_dir, background_image, num_frames, progress_queue)
        for i in range(num_processes)
    ]

    with multiprocessing.Pool(processes=num_processes) as pool:
        with tqdm(total=num_frames, unit='frame', desc='Gerando frames') as pbar:
            results = pool.map_async(generate_frames_chunk, args_list)
            
            while not results.ready():
                frames_processed = progress_queue.qsize()
                if frames_processed > 0:
                    pbar.update(frames_processed)
                    for _ in range(frames_processed):
                        progress_queue.get()
                time.sleep(0.1)

            frames_processed = progress_queue.qsize()
            if frames_processed > 0:
                pbar.update(frames_processed)

    # Verificar se todos os frames foram gerados
    expected_frames = num_frames
    generated_frames = len([f for f in os.listdir(output_dir) if f.endswith('.jpg')])
    if generated_frames < expected_frames:
        print(f"Aviso: Apenas {generated_frames} de {expected_frames} frames foram gerados.")
    else:
        print(f"Todos os {expected_frames} frames foram gerados com sucesso.")


def create_video(frame_folder, output_video, audio_file):
    frame_pattern = os.path.join(frame_folder, 'frame_%04d.jpg')
    duration = get_audio_duration(audio_file)
    fade_out_start = duration - FADE_DURATION

    command = [
        'ffmpeg',
        '-y',
        '-framerate', str(FPS),
        '-i', frame_pattern,
        '-i', audio_file,
        '-c:v', 'h264_nvenc',
        '-preset', 'medium',
        '-rc', 'vbr_hq',
        '-cq', '23',
        '-b:v', '10M',
        '-maxrate', '20M',
        '-bufsize', '20M',
        '-profile:v', 'high',
        '-c:a', 'aac',
        '-profile:a', 'aac_low',
        '-b:a', '448k',
        '-vf', f"fade=t=in:st=0:d={FADE_DURATION},fade=t=out:st={fade_out_start}:d={FADE_DURATION}",
        '-shortest',
        output_video
    ]
    subprocess.run(command, check=True)


def main():
    try:
        subtitles = read_subtitles('legenda.srt')
        output_dir = 'frames'
        os.makedirs(output_dir, exist_ok=True)

        background_image_path = r"C:\Users\lucas\OneDrive\Documentos\capa.jpg"
        background_image = Image.open(background_image_path).convert("RGBA").resize(IMAGE_SIZE)

        generate_frames_parallel(subtitles, output_dir, background_image)
        create_video(output_dir, 'output_video.mp4', 'audio.wav')
        shutil.rmtree(output_dir)
    except Exception as e:
        print(f"Erro durante a execução do programa: {str(e)}")


if __name__ == "__main__":
    main()
```