[Python] Traduttore automatico di sottotitoli

La mia smodata passione per le serie tv made in USA mi ha iniziato al binge watching molto prima che ne venisse coniato il termine per diventare una moda. Ricordo ancora il week end di una decina di anni fa, passato a ‘recuperare’ su internet gli episodi delle prime tre stagioni di «Battlestar Galactica» poco prima della trasmissione in America della quarta stagione. Di lì ho scoperto che non mi piaceva attendere qualche anno prima di poter guardare una serie tv che mi interessava e che internet da questo punto di vista era una notevole risorsa se si era disposti ad abituare l’occhio a non perdersi nessuna scena sbirciando contemporaneamente i sottotitoli sullo schermo (ancora tante grazie Italiansubs!).


Ora che i sottotitoli in italiano si fa più fatica a trovarli, un po’ per gioco e un po’ per utilità, ho pensato di creare uno script in Python che traduce un file di sottotitoli in inglese nel corrispettivo in italiano utilizzando la libreria googletrans (link) che sfrutta l’API di Google Translate. Il risultato non sarà dei più corretti ma IMHO abbastanza accettabile per godersi un episodio della propria serie tv preferita.


Ingredienti:

    • python 3
    • libreria googletrans (per la traduzione)
    • librerie sys, os (per la gestione dei file)
    • libreria timeit (per computare le prestazioni)

Per installare la libreria avendo a disposizione l’utility PIP è sufficiente digitare il seguente comando:

pip install googletrans

Analizziamo le parti principali del sorgente:

Innanzitutto importiamo le librerie che ci necessitano:

import sys, os
from googletrans import Translator
from timeit import default_timer as timer

Memorizziamo in una variabile il tempo iniziale che ci servirà per calcolare successivamente le prestazioni dello script:

start = timer()

E inizializziamo il traduttore sull’API pubblica di Google Translate:

translator = Translator(service_urls=[
      'translate.google.com',
      'translate.google.it',
    ])

Il progetto prevede di dare in pasto al traduttore le frasi contenute in un file in formato .srt contenente i sottotitoli in inglese, strutturalmente fatto in questo modo:

Per quanto riguarda il nome del file da tradurre lo passeremo come argomento nell’istruzione di esecuzione del programma. Il nome del file prodotto con i sottotitoli tradotti in italiano sarà generato conseguentemente aggiungendo il suffisso “_tradotto”. Viene anche controllata l’esistenza di un eventuale precedente file di traduzione avente lo stesso nome di quello in produzione e nel caso verrà cancellato.

try:
sourcefile = sys.argv[1]
resultfile = sys.argv[1].replace('.srt', '')+'_tradotto.srt'
except:
sourcefile = "sottotitolo.srt"
resultfile = sourcefile.replace('.srt', '')+'_tradotto.srt'

if os.path.isfile(resultfile) == True:
os.remove(resultfile)

Nessun problema ad aprire il file in questione e scomporre le righe di testo in elementi di una lista. Inoltre già che ci siamo cancelliamo gli eventuali inutili spazi vuoti in testa e in coda a ciascuna riga con il metodo strip():

with open(sourcefile) as f:
    content = f.readlines()
content = [x.strip() for x in content]

Ovviamente al nostro traduttore dovremo passare ‘solo’ i testi e non gli altri elementi utili alla renderizzazione a video dei sottotitoli. Inoltre al traduttore dobbiamo passare delle frasi intere, anche se nel file dovessero risultare ‘spezzate’ su più righe.

Processiamo ciascuna riga della lista creata e scartiamo quelle righe (senza eliminarle perché ci occorreranno poi per scrivere correttamente il file .srt dei sottotitoli tradotti) contenenti un numero intero (cioè il numero del sottotitolo) piuttosto che la durata del sottotitolo (che Python vede comunque come una stringa di testo da qui la trovata di pulire la riga dal segno di separazione (“:”) e di considerarne solo i primi 5 caratteri, in modo che ad esempio la riga “00:00:03,886 –> 00:00:07,961” venga computata come “00000” che Python riconosce giustamente come numero e quindi ce la fa scartare:

for item in content:
    count += 1
    if item.isdigit() == False:
        try:
            control = item.replace(":","")
            part = control[0:4].isdigit()
        except:
            part = False

Per risolvere il problema delle frasi spezzate su più righe come abbiamo ad esempio in questo caso:

Dove per ottenere una traduzione corretta occorre passare al traduttore una corretta frase interaBut you won’t fix the real problem” e non due righe separate come si presentano nel file. Si andrà quindi a tradurre quanto memorizzato in una lista ‘volatile’ solo dopo aver incontrato un salto di riga vuoto come questo:

Di seguito la mia soluzione che memorizza il testo da tradurre nella stringa “datradurre” che viene passata al traduttore istanziando l’oggetto translations da cui ricaviamo il testo tradotto quando la variabile trigger ‘accio’ processa una riga vuota. Ovviamente occorre tenere conto che sebbene al traduttore la frase di due righe verrà fornita in una riga sola, al momento della ricostruzione del sottotitolo tradotto la frase dovrà essere nuovamente divisa se troppo lunga per non perdere in leggibilità del sottotitolo: la frase sarà ‘spezzata in due righe dovesse essere composta da più di 5 parole e comunque da più di 40 caratteri (esclusi i segni ‘speciali di renderizzazione). Dopo aver passato la stringa al traduttore questa viene azzerata, pronta per le righe successive. Il tutto viene memorizzato in una lista denominata ‘traduzione’ a cui si aggiungeranno man mano tutte le righe processate, comprendenti il numero del sottotitolo, i tempi di inizio e fine visualizzazione e la traduzione ottenuta (o il testo originale se il programma non è riuscito a tradurre).

       if part != True:
            datradurre = datradurre +' '+item
            datrad_non.append(datradurre)
            accio = ("_______"+str(item)+"________________>")
            if accio == "_______________________>":
                try:
                    translations = translator.translate(datradurre, src='en', dest='it')
                    trad = translations.text
                    parole = 0
                    a = trad.split(" ")
                    for i in a:
                        if (i!=" " and i!="<i>" and i!="</" and i!="i>" and i!="-" and i!="..."):
                            parole=parole+1
                    if parole >5 and len(trad) >40:
                        frase = range(6,parole)
                        primariga = str(a[0])+' '+str(a[1])+' '+str(a[2])+' '+str(a[3])+' '+str(a[4])+' '+str(a[5])
                        secondariga = ''
                        for x in frase:
                            secondariga = secondariga+' '+str(a[x])
                        traduzione.append(primariga)
                        traduzione.append(secondariga[1:])
                        traduzione.append(item)
                        TRcount += 1
                    else:
                        traduzione.append(trad)
                        traduzione.append(item)
                        TRcount += 1
                except:
                    for x in datrad_non:
                        traduzione.append(x)
                    traduzione.append(item)
                    NOcount += 1
                datradurre = ""
                datrad_non.clear()
        else:
            traduzione.append(item)

Dopo aver processato tutte le righe si può procedere a generare scrivendo riga per riga il file .srt con i sottotitoli tradotti:

with open(resultfile, 'a') as f:
    for item in traduzione:
        f.write(item+'\n')

Possiamo calcolare a questo punto il tempo di esecuzione in secondi del programma:

end = timer()
tempo = "{0:.2f}".format((end - start))

E infine visualizzare le statistiche raccolte con i vari contatori alimentati durante il processo di traduzione:

print('\n')
print ('Totale righe _________ '+str(count))
print ('Totale traduzioni ____ '+str(TRcount))
print ('Problemi traduzioni __ '+str(NOcount))
print ('Totale tempo _________ '+tempo+'s')
print('\n')

Non sarà lo script meglio scritto, ma in un tempo ragionevole (circa 300 secondi per processare un episodio di tre quarti d’ora) riesce a sfornare dei sottotitoli in italiano discretamente accettabili.

Codice sorgente completo disponibile su GITHUB (link).

CITTADINO IMPERFETTO: I migliori articoli del 2018

Come ormai tradizione pubblichiamo una rassegna dei post più gettonati dell’anno appena trascorso.


Titolo Post   Views 2018

  1. Il router wifi va spento durante la notte?

 

7.4k

  2. Problema “Memoria quasi piena” su Samsung Galaxy

 

6.7k

  3. Utilizzare HyperTerminal in WINDOWS 7

 

6.2k

  4. Come vedere la televisione con VLC e una chiavetta USB DVB-T

 

 5.4k

  5. Come fare in casa la Ginger beer

 

 4.2k

  6. [Risolto] Aiuto!!! Non riesco a disinstallare Microsoft Office

 

  4.1k

  7. [RISOLTO] Come trovare l’ICCID della SIM in Windows Mobile 10

 

 4.0k

  8. Testare e riparare le chiavette USB con Check Flash 1.08

 

 3.5k

  9. [Risolto] Installazione Windows 7: “codice errore: 0x80070017”

 

  2.6k

10. Testare e riparare le chiavette USB con Check Flash 1.10

 

  2.5k


Un ringraziamento per averci seguito così numerosi.
Da parte nostra ce la metteremo sempre tutta per postare articoli interessanti.

Buon 2019!!!


Link migliori articoli 2017
Link migliori articoli 2016
Link migliori articoli 2015
Link migliori articoli 2014
Link migliori articoli 2013
Link migliori articoli 2012
Link migliori articoli 2011
Link migliori articoli 2010
Link migliori articoli 2009

[Google – doodle] Buon Anno 2019

Le solite vittime della guerra giusta

Non è passato che un secolo dalla fine della Prima Guerra Mondiale (1914-1918). Qualche celebrazione, ma niente che abbia seriamente scalfito il muro di gomma d’indifferenza delle coscienze, oggi come non mai concentrate solo sul presente. Eppure la Storia avrebbe tra i suoi compiti proprio quello di serbare memoria non solo dei successi e dei traguardi raggiunti, ma soprattutto degli errori compiuti nel passato.

La Storia è quindi principale nemica del Sistema che la combatte con l’arma più efficiente a sua disposizione: l’oblio. Così anche se le piazze rimangono infarcite di statue commemorative e magari una volta l’anno si coglie l’occasione di una vacanza, l’inevitabile sottilmente si compie. L’oblio ha infine la meglio sfruttando l’umana propensione della mente a lenire le ferite cercando di dimenticare i mali passati pure al prezzo di restare all’oscuro di ciò di cui si stati vittima.

Eppure la Storia (la storiografia nel senso più alto del termine) rimane sempre a disposizione degli uomini di buona volontà che aspirano ad emanciparsi dalla schiavitù dell’ignoranza. E’ sufficiente sfogliare una delle sue tante pagine per scorgere attraverso la sapiente luce della conoscenza i meccanismi alla base del funzionamento di questo mondo.

E così la Prima Guerra Mondiale mostra il suo vero volto. Un immane e insensato massacro responsabilità di pochi cinici sulla pelle delle moltitudini. Non una guerra giusta, moralmente accettabile, ma uno strumento di chi ha il potere per legittimarsi e ottenere quel consenso di cui voracemente si alimenta.

Restando nel cortile del nostro paese, sfrondata la retorica dalla risorgimentale volontà di completare l’unità nazionale, dal patriottismo degli interventisti e dall’isolazionismo dei neutralisti, rimane il grosso macigno dell’ignoranza sui fatti dei milioni che realmente poi persero la vita al fronte.

E così ancora una volta la più importante lezione della Storia riguarda chi ha il potere di scatenare una guerra che quasi mai scende in trincea a versare il suo sangue che a morire ci manda proprio quella gente di cui millanta di perseguire gli interessi.

Chi è convinto che la Storia sia roba noiosa che poco o niente ha di che spartire con il presente e meno con il futuro, non ha capito un bel niente.

Se ad esempio si trova il coraggio di trasporre quanto sopra all’attualità dei giorni nostri, si è magari in grado di scoprire qualche altarino. Oggi la guerra dove si spara e si sganciano bombe la si fa nel terzo mondo dove la gente è più avvezza a questo modo di fare che quando qualche anno fa ha provato a lambirci più da vicino non ci abbiamo per niente fatto una bella figura. Qui noi la guerra, che rimane sempre una questione di vile denaro, la si combatte senza esercito che impieghiamo solo nelle cosiddette missioni di pace. Da noi la guerra è commerciale e se magari sfiora la politica rimane sempre relegata a questione di interessi economici.

E mentre una delle idee più nobili scaturite dalle rovine della Seconda Guerra Mondiale è fatalmente in crisi, lontana dalle origini e dai condivisibili ideali, impastoiata negli aspetti legati alla finanza, la nostra guerra è contro i burocrati dell’Unione Europea. Chi ci comanda ci infarcisce le orecchie con la retorica del sovranismo e del populismo (unità nazionale? patriottismo?) e ci vorrebbe sul fronte a combattere la guerra per tutelare i nostri interessi (?). E se sfortuna vorrà che si compirà un massacro, quelli che ci rimetteranno non saranno chi sta sopra, ma (in questo caso) i soldi della povera gente.

E questa quindi una nuova guerra giusta?

La Storia potrebbe rispondere di no, ma sembra che nessuna abbia bisogno dei suoi consigli. Il passato si vorrebbe fosse come quell’acqua che non passa mai due volte sotto lo stesso ponte. Ma per fortuna c’è chi non ne è per niente convinto e tra le coltri della nebbia dell’ignoranza riesce ad intravvedere il vero nemico ovvero quel Sistema che ha interesse solo a tutelare se stesso.

Buone Feste!

Risotto al sapore di cernia

Il risotto è un piatto amoroso che ti riempie di gusto. Ogni boccone di riso portato alla bocca restituisce i sapori che ha raccolto durante la caratteristica cottura. La cipolla del soffritto si nasconde tra i chicchi arricchiti dalla sapidità del brodo. Il pesce viene esaltato dall’amidosa cremina resa dalla sapiente mantecatura finale. Che bel mangiare!


Ingredienti per 3/4 persone:

  • 300g. di riso carnaroli;
  • 200g. di  filetti di cernia;
  • 1 filetto di acciuga;
  • 1 spicchio d’aglio;
  • 1 cipolla bianca;
  • 1 filetto di acciuga;
  • 1 carota;
  • 1 mazzetto di prezzemolo
  • 50g di burro;
  • 1 cucchiaiono di paprica forte;
  • 1 cucchiaino di aglio in polvere;
  • 30g. di farina 00;
  • olio e.v.o.;
  • due cucchiai di passata di pomodoro;
  • 1/2 bicchiere di vino bianco secco;
  • sale e pepe.

Tempi:

    35 minuti circa

Preparazione:

  • Innanzitutto prepariamo il brodo: ad un litro di acqua fredda aggiungiamo 1/2 cipolla, la carota, l’aglio e i rametti del prezzemolo, quindi saliamo, portiamo a bollore e lasciamo cucinare per 15′.
  • In una pentola capace soffriggiamo in una noce di burro e due cucchiai di olio,  la cipolla tagliata a cubetti (grandi come chicchi di riso) e il filetto di acciuga;
  • Senza far imbiondire troppo la cipolla aggiungiamo il riso per farlo tostare per circa un minuto a fuoco medio;
  • Sfumiamo con il vino bianco, quindi aggiungiamo il primo mestolo di brodo filtrato e bollente;
  • Proseguiamo la cottura a fuoco medio/basso, aggiungendo di volta in volta il brodo necessario a coprire, senza sommergere il riso che non va mai mescolato troppo;
  • A metà cottura aggiungere metà della cernia ridotta a tocchetti e la passata di pomodoro;
  • L’altra metà della cernia va ridotta a filetti rettangolari che vanno salati e infarinati con farina, paprica forte e aglio in polvere, quindi fritti in olio e burro e poi tenuti al caldo.
  • Portare quasi a termine la cottura del riso quindi mantecare con un cucchiaio scarso di olio e le foglie del prezzemolo tritato (magari una macinata di pepe), quindi lasciare riposare qualche minuto con il coperchio in modo da arrivare alla giusta consistenza del riso;
  • Impiattare il riso con in cima qualche filetto di cernia fritta. Servire ben caldo.

[ SPOT ] «Mamma ho perso l’aereo» al tempo di Google Assistant

Sono passati quasi trent’anni da quando una mia versione più mocciolosa rimase a bocca aperta di fronte alle imprese del piccolo Kevin McCallister lasciato erroneamente da solo a casa durante le festività natalizie a fronteggiare con il suo ingegno da bambino i ladri cattivi.

Un film divenuto quasi da subito un cult del genere, che fortunatamente la televisione ripropone ogni anno a cavallo di Natale e Capodanno alla stregua di “Una poltrona per due” senza il quale al Natale mancherebbe qualcosa tipo la scintillante punta dell’albero addobbato e/o il calore del bue nel presepe.

I ragazzi di MountView hanno ben pensato di sdoganare il loro Google Assistant al grande pubblico riproponendo alcune scene iconiche del film Mamma ho perso l’aereo interpretate da un più maturo Macaulay Culkin che oggi ha a disposizione le moderne tecnologie per fronteggiare i cattivi senza fare molta fatica. 

In questo caso la pubblicità è così ben fatta e ben pensata da far dimenticare per un attimo di essere spettatori dell’ennesimo strumento di marketing e di godere di essere trasportati per qualche secondo nei ricordi della nostra magica infanzia.

Comunque in concomitanza di questa campagna pubblicitaria e quindi per un tempo limitato (e presumibilmente solo per il mercato anglofono), Google Assistant risponderà così ai seguenti comandi vocali:

  • “Did I forget something?” – farà esclamare al dispositivo il celebre “KEVIN!!!!”
  • “How much do I owe You?” o “It’s me Snakes. I got the Stuff” – farà ricreare il dialogo del film che guarda Kevin, creato appositamente per il film, “Angels with filthy souls”
  • “The Wet Bandits are here” – farà sentire cosa farebbe Kevin in uno dei momenti più iconici del film
  • “I’m the man of the house” – farà rivivere la scena in cui Kevin si mette il dopobarba

 

%d blogger hanno fatto clic su Mi Piace per questo: