dotfiles

Repositório dotfiles
git clone git://git.sivaldodavi.com/dotfiles.git
Log | Files | Refs | README

yt-sub (5209B)


      1 import sys
      2 import subprocess
      3 import glob
      4 import re
      5 import argparse
      6 
      7 def clean_vtt(filepath, remove_time=True, words_per_paragraph=150):
      8     """
      9     Limpa o arquivo VTT, remove duplicatas e junta o texto em blocos baseados 
     10     em uma quantidade limite de palavras por parágrafo.
     11     """
     12     with open(filepath, "r", encoding="utf-8") as f:
     13         lines = f.readlines()
     14 
     15     cleaned_content = []
     16     last_text_line = ""
     17 
     18     # Padrões Regex para identificar lixo e tempos
     19     time_pattern = re.compile(r'-->')
     20     header_pattern = re.compile(r'^WEBVTT|^Kind:|^Language:|^Align:|Style:')
     21     number_pattern = re.compile(r'^\d+$')
     22     tags_pattern = re.compile(r'<[^>]+>') # Remove tags como <00:00:01.000> ou <c>
     23 
     24     for line in lines:
     25         original_line = line.strip()
     26 
     27         # Pula linhas vazias
     28         if not original_line:
     29             if not remove_time:
     30                 cleaned_content.append("\n")
     31             continue
     32 
     33         # Ignora cabeçalhos e números de indexação
     34         if header_pattern.search(original_line) or number_pattern.match(original_line):
     35             if not remove_time:
     36                 cleaned_content.append(original_line + "\n")
     37             continue
     38 
     39         # Lida com o tempo
     40         if time_pattern.search(original_line):
     41             if not remove_time:
     42                 cleaned_content.append(original_line + "\n")
     43             continue
     44 
     45         # Extrai apenas o texto limpo
     46         text = tags_pattern.sub('', original_line).strip()
     47 
     48         if not text:
     49             continue
     50 
     51         # Lógica para evitar as duplicações do YouTube (legendas rolantes)
     52         if text != last_text_line:
     53             if remove_time:
     54                 # Se for sem tempo, junta tudo na mesma linha separando por espaço
     55                 cleaned_content.append(text + " ")
     56             else:
     57                 # Se for com tempo, mantém a quebra de linha do VTT
     58                 cleaned_content.append(text + "\n")
     59             
     60             last_text_line = text
     61 
     62     final_text = "".join(cleaned_content)
     63 
     64     # Se estiver no modo texto (sem tempo), organiza em parágrafos por contagem de palavras
     65     if remove_time:
     66         # Remove espaços duplos que possam ter sobrado
     67         final_text = re.sub(r'\s+', ' ', final_text).strip()
     68         
     69         # Divide o texto todo em uma lista de palavras
     70         palavras = final_text.split()
     71         
     72         # Agrupa as palavras em blocos (parágrafos) do tamanho definido
     73         paragrafos = []
     74         for i in range(0, len(palavras), words_per_paragraph):
     75             bloco_palavras = palavras[i : i + words_per_paragraph]
     76             paragrafo = " ".join(bloco_palavras)
     77             paragrafos.append(paragrafo)
     78             
     79         # Junta os parágrafos com duas quebras de linha entre eles
     80         final_text = "\n\n".join(paragrafos)
     81 
     82     # Sobrescreve o arquivo com a versão final
     83     with open(filepath, "w", encoding="utf-8") as f:
     84         f.write(final_text)
     85 
     86 def process_url(url, keep_time, words_per_paragraph):
     87     print(f"\n--- Processando: {url} ---")
     88     
     89     # Lista arquivos antes para saber qual foi baixado agora
     90     vtts_antes = set(glob.glob("*.vtt"))
     91     
     92     # Comando base (silencioso)
     93     comando_base = [
     94         "yt-dlp",
     95         "--quiet",
     96         "--no-warnings",
     97         "--write-subs",
     98         "--write-auto-subs",
     99         "--sub-format", "vtt",
    100         "--skip-download",
    101         url
    102     ]
    103     
    104     # 1. TENTA BAIXAR EM PORTUGUÊS
    105     print("Buscando legenda em PT...")
    106     comando_pt = comando_base[:5] + ["--sub-langs", "pt"] + comando_base[5:]
    107     subprocess.run(comando_pt)
    108     
    109     vtts_depois = set(glob.glob("*.vtt"))
    110     novos_vtts = vtts_depois - vtts_antes
    111     
    112     # 2. SE NÃO ACHOU, TENTA EM INGLÊS
    113     if not novos_vtts:
    114         print("Legenda em PT não encontrada. Tentando EN...")
    115         comando_en = comando_base[:5] + ["--sub-langs", "en"] + comando_base[5:]
    116         subprocess.run(comando_en)
    117         
    118         vtts_depois = set(glob.glob("*.vtt"))
    119         novos_vtts = vtts_depois - vtts_antes
    120         
    121     # SE CONTINUAR SEM ACHAR, ABORTA
    122     if not novos_vtts:
    123         print("Nenhuma legenda encontrada (nem PT, nem EN).")
    124         return
    125 
    126     # Limpa os arquivos recém-baixados
    127     for arquivo in novos_vtts:
    128         print(f"Limpando e formatando arquivo em blocos de {words_per_paragraph} palavras: {arquivo}")
    129         clean_vtt(arquivo, remove_time=not keep_time, words_per_paragraph=words_per_paragraph)
    130         
    131     print("Processo concluído com sucesso!")
    132 
    133 def main():
    134     parser = argparse.ArgumentParser(description="Baixa legendas (PT ou EN) e formata em grandes blocos de texto.")
    135     
    136     parser.add_argument("urls", nargs="+", help="Uma ou mais URLs do YouTube.")
    137     parser.add_argument("-t", "--keep-time", action="store_true", 
    138                         help="Mantém as tags de tempo (formato VTT original, sem juntar os blocos).")
    139     parser.add_argument("-w", "--words", type=int, default=150, 
    140                         help="Quantidade de palavras por parágrafo (Padrão: 150).")
    141 
    142     args = parser.parse_args()
    143 
    144     for url in args.urls:
    145         process_url(url, keep_time=args.keep_time, words_per_paragraph=args.words)
    146 
    147 if __name__ == "__main__":
    148     main()