Category Archive Tecnologia

Twitch in streaming dal flusso di una webradio

Twitch è un servizio di streaming video, utilizzato principalmente dai giocatori, che può essere utilizzato anche per un altro scopo. Come forse già saprai, sono un Digital Streaming Specialist in una web radio, radiocittaperta.it. Twitch può essere utilizzato per una web radio o una radio? Come può una web radio utilizzare le funzionalità video di Twitch?

Ci sono radio e web radio che usano Twitch per lo streaming dei loro contenuti, per lo più usano alcune webcam in studio e aggiungono l’audio in streaming della radio al video. Sembra una radiovisione, come quella che puoi trovare sul digitale terrestre. Le tecnologie possono ottenere su Twitch lo stesso risultato di quello che trovi sul digitale ma con meno spese. Twitch è gratuito, il software di streaming può essere gratuito (OBS è un software gratuito per farlo), devi acquistare una o più videocamere e dell’hardware di acquisizione video, ma puoi vedere tutte queste cose con il budget che hai.

Se non disponi affatto di un budget e non desideri aggiungere un video reale ripreso da una videocamera allo streaming audio della tua web radio, puoi creare un video digitale con i seguenti passaggi. L’idea è di:

  1. Usare un’immagine statica
  2. Aggiungere del contenuto dinamico, ad esempio un video creato direttamente dalla sorgente audio
  3. Aggiungere l’audio in streaming

Potresti pensare di aver bisogno di un software sempre aperto su un computer, ma esiste una soluzione migliore: usa ffmpeg per farlo e lascia che ffmpeg venga eseguito in background su un computer. Ho già scritto di ffmpeg e di alcune delle sue funzioni. Con questa soluzione puoi eseguirlo su un computer utilizzato anche per altro, su un server o anche su un RaspberryPi connesso a internet. E questa è roba molto interessante! Che ti serve?

  • La chiave twitch, è una cosa fatta così live_238476238546_234jhgfuowgsjdhbfwsDFSdgbjsbv
  • L’audio stream https://my.audio.stream:port/stream
  • Un immagine statica /somepath/mystaticimage.jpg

dopodiché basta lanciare questo comando


ffmpeg -loop 1 -f image2 -thread_queue_size 256 -i /somepath/mystaticimage.jpg \
-thread_queue_size 256 -i https://my.audio.stream:port/stream -re \
-nostdin \
-f lavfi -i aevalsrc="sin(0*2*PI*t)" \
-vcodec libx264 -r 30 -g 30 \
-preset fast -vb 3000k -pix_fmt rgb24 \
-pix_fmt yuv420p -f flv \
-filter_complex \
"[1:a]showwaves=s=960x100:colors=Red:mode=cline:rate=25:scale=sqrt[outputwave]; \
[0:v][outputwave] overlay=0:510:shortest=1 [out]" \
-map '[out]' -map '1:a' -c:a copy -y \
rtmp://live-ber.twitch.tv/app/live_238476238546_234jhgfuowgsjdhbfwsDFSdgbjsbv \
-loglevel quiet 2> /dev/null &

qualche nota su questo comando: 

  • [0:v][outputwave] overlay=0:510:shortest=1 [out]" 

    imposta dove viene stampata la forma d’onda, 510 è “a quale altezza” puoi giocare con quel valore per spostare la forma d’onda in alto o in basso.

  • "[1:a]showwaves=s=960x100:colors=Red:mode=cline:rate=25:scale=sqrt[outputwave];

    è il creatore della forma d’onda. C’è il colore e come deve essere stampata la forma d’onda, controlla la documentazione di ffmpeg per altre configurazioni

  • -loglevel quiet 2> /dev/null &

    serve a mettere il comando in background

E questo è il risultato finale (alcuni secondi)

Riconoscere il silenzio da un input audio su Linux

Come Digital Streaming Specialist per una web radio (Radio Città Aperta) ho sempre nuove sfide e problemi da risolvere.
In una grande società c’è sempre la scelta tra “fare o comprare?” ma quando il tuo mondo è piccolo, senza finanziamenti, e con tanto entusiasmo ma poco tempo, devi trovare soluzioni adatte a tutte le tue esigenze. Non solo una soluzione deve essere economica: deve anche essere facile da capire, facile da mantenere, dovrebbe funzionare senza intervento manuale e cose del genere.

Il problema attuale è “come capire che la web radio è in streaming, quando lo streaming è muto?”

come capire che la web radio è in streaming, quando lo streaming è muto?

Perchè succede? Lo streaming della web radio è una catena di più parti, sia analogiche che digitali, e può capitare che alcune di esse siano mute, mentre altre funzionino come previsto. Ad esempio, supponiamo di avere un computer che funziona come nostro streamer; sta inviando l’input audio acquisito da una scheda audio direttamente a un server streamer. Anche se internet funziona, c’è la connessione, la password è nota e l’host è ok, non c’è modo di capire se l’audio catturato sia muto o meno. Ciò si traduce in uno streaming audio attivo e funzionante, ma che non produce audio (o forse si può sentire solo del rumore bianco).

Se il cavo di ingresso è staccato, se la sorgente audio è spenta o se il fader del mixer è completamente giù invece di essere al massimo volume, tutte queste situazioni possono portare a un audio silenzioso che passa attraverso la catena di streaming. La soluzione ottimale per questo è qualcosa che monitora in tempo reale l’audio in ingresso, controlla se ci sono almeno X secondi di silenzio e, se ciò accade, avvia alcune procedure che possono essere:

  • avviare una playlist in modo che l’audio non sia più silenzioso
  • inviare una e-mail e/o un avviso a qualcuno

Inoltre, quando l’ingresso audio non è più silenzioso (ad esempio, uno speaker della radio super intelligente ha spostato il fader del mixer nella posizione corretta…), questo software deve interrompere la riproduzione della playlist. Deve essere eseguito per sempre, deve essere riavviato se viene arrestato e deve essere eseguito all’avvio. Quindi iniziamo con qualcosa che ho trovato: Python hasounddevice che fa quello che ci serve. 

Sounddevice con Python

Non un campione di Python, ma sembra molto facile da capire, facile da usare, facile da modificare e super potente. Ho iniziato da questo thread con questo frammento di codice

# Print out realtime audio volume as ascii bars

import sounddevice as sd
import numpy as np

def print_sound(indata, outdata, frames, time, status):
    volume_norm = np.linalg.norm(indata)*10
    print ("|" * int(volume_norm))

with sd.Stream(callback=print_sound):
    sd.sleep(10000)

che mostra alcune barre del livello di ingresso audio. Con qualche modifica, una catena di “if” ho modificato lo script in modo che scriva su un file quando vengono trovati X campioni silenziosi. Silent è definito come “un livello sotto la soglia, th.
 

#!/usr/bin/env python3

import numpy as np
import sounddevice as sd
import datetime


duration = 10 #in seconds

th = 10
sec = 0
maxNumberOfSilent = 4000
isSilent = True
logfile = open("soundlevel.log", "a")

def audio_callback(indata, frames, time, status):
	global sec
	global isSilent
	global logfile
	dateLog = datetime.datetime.now().strftime("[%Y-%m-%d %H:%M:%S] ")
	volume_norm = np.linalg.norm(indata) * 10 
	#print("|" * int(volume_norm))
	#print(volume_norm)
	if volume_norm < th: sec += 1 else: sec = 0 if (sec > maxNumberOfSilent and not isSilent):
		 isSilent = True
		 logfile.write(dateLog+"Silent for "+str(maxNumberOfSilent)+" samples\n")
		 logfile.flush()
		 #print("Silent for "+str(maxNumberOfSilent)+" samples")
	elif (sec == 0 and isSilent):
		 isSilent = False
		 logfile.write(dateLog+"Music\n")
		 logfile.flush()
		 #print("Music")


stream = sd.InputStream(callback=audio_callback)
with stream:
	while (True):
		sd.sleep(duration * 1000)

Dopo qualche altra ricerca, ho trovato una classe per inviare e-mail utilizzando un account Gmail:

import smtplib, ssl

class Mail:

    def __init__(self):
        self.port = 465
        self.smtp_server_domain_name = "smtp.gmail.com"
        self.sender_mail = "........"
        self.password = "........"

    def send(self, emails, subject, content):
        ssl_context = ssl.create_default_context()
        service = smtplib.SMTP_SSL(self.smtp_server_domain_name, self.port, context=ssl_context)
        service.login(self.sender_mail, self.password)
        
        for email in emails:
            result = service.sendmail(self.sender_mail, email, f"Subject: {subject}\n{content}")

        service.quit()


if __name__ == '__main__':
    mails = input("Enter emails: ").split()
    subject = input("Enter subject: ")
    content = input("Enter content: ")

    mail = Mail()
    mail.send(mails, subject, content)

 
Per mettere tutto insieme, ho creato un sistema che invia una e-mail quando il suono è silenzioso:

#!/usr/bin/env python3

import numpy as np
import sounddevice as sd
import datetime
import smtplib, ssl

th = 10
sec = 0
maxNumberOfSilent = 10000
isSilent = True
logfile = open("soundlevel.log", "a")
to_addresses = ("myemail@mail.com",)


class Mail:

    def __init__(self):
        self.port = 465
        self.smtp_server_domain_name = "smtp.gmail.com"
        self.sender_mail = "....."
        self.password = "...."

    def send(self, emails, subject, content):
        ssl_context = ssl.create_default_context()
        service = smtplib.SMTP_SSL(self.smtp_server_domain_name, self.port, context=ssl_context)
        service.login(self.sender_mail, self.password)

        for email in emails:
            result = service.sendmail(self.sender_mail, email, f"Subject: {subject}\n{content}")

        service.quit()

mail_client = Mail()
def audio_callback(indata, frames, time, status):
   global sec
   global isSilent
   global logfile
   dateLog = datetime.datetime.now().strftime("[%Y-%m-%d %H:%M:%S] ")
   volume_norm = np.linalg.norm(indata) * 10 
   #print("|" * int(volume_norm))
   #print(volume_norm)
   if volume_norm < th: sec += 1 else: sec = 0 if (sec > maxNumberOfSilent and not isSilent):
       isSilent = True
       logfile.write(dateLog+"Silent for "+str(maxNumberOfSilent)+" samples\n")
       logfile.flush()
       mail_client.send(to_addresses,"Audio is silent",dateLog+" audio is silent") 
       #print("Silent for "+str(maxNumberOfSilent)+" samples")
   elif (sec == 0 and isSilent):
       isSilent = False
       logfile.write(dateLog+"Music\n")
       logfile.flush()
       mail_client.send(to_addresses,"Audio back to normal",dateLog+" audio back to normal") 
       #print("Music")

stream = sd.InputStream(callback=audio_callback)
with stream:
   while (True):
      sd.sleep(10 * 1000)
Second implementation podcast player

Un player di podcast per un sito di una web radio

Per hobby, sono il “tuttofare del software” in una web radio (anche speaker per la verità). Nel mio tempo libero, cerco di trovare soluzioni e cose interessanti per tutti i problemi digitali legati a questa attività. Potrebbe essere qualcosa che deve essere automatizzato o alcune cose interessanti sul sito web. Questa volta, nonostante io non sia un buon UI/UX, ho cercato di migliorare il riproduttore di podcast sul sito web. Il web player predefinito di WordPress non è poi così male, ma sperimentare è qualcosa che mi piace fare e, dopotutto, nessuno verrà ucciso da un esperimento di cattivo player su un sito web radio autofinanziato dal suo relatore. Quindi ho visto alcuni giocatori fantastici con una forma d’onda su di esso e ho passato del tempo a capire come possono essere inclusi.

 

default worpdress player

Player di default di worpdress

Prima iterazione di un nuovo player

Dopo una prima implementazione, ho trovato la versione 1 di questo nuovo player non così dinamica come mi aspettavo. Inoltre, richiedeva anche alcuni calcoli e file aggiuntivi (un file statico che rappresenta il picco della forma d’onda).

 

First Implementation podcast player

Prima iterazione di un player

Seconda iterazione di un player

Quindi ho trovato un nuovo lettore super dinamico, in javascript. Ma mi ha dato alcuni problemi legati all’evento “touch” necessario agli utenti di iPhone per avviare il suono. Dopo alcuni mesi passati a capire come risolverlo, ho finalmente trovato un modo per farlo funzionare.

 

Second implementation podcast player

Seconda iterazione di un palyer per podcast

Non è perfetto, si può ancora fare meglio e forse ci sono dei bug, ma quello che voglio evidenziare è il fatto che ho passato molto del mio tempo libero a trovare una soluzione migliore (meglio significa “meglio per me”) e risoluzione di problemi, problemi, casi limite, limitazioni del codice. Guarda questo video di riepilogo:

 

 

Ho avuto la possibilità di farlo perché non ci sono soldi, né vite umane coinvolte e, fondamentalmente, perché questo è un hobby. La possibilità di sperimentare in un ambiente sicuro ha fatto la differenza e mi ha dato anche una visione di quali sono le altre diverse competenze e persone coinvolte nello sviluppo di una soluzione software: quale potrebbe essere il problema per una UX, cosa potrebbe spingere ad aggiungere un nuova soluzione basata anche sul tempo necessario per realizzarla.

Il mio consiglio è di trovare spazio per esplorare e commettere errori sul posto di lavoro o al di fuori del posto di lavoro. Se hai tempo dai un’occhiata al player, al sito e, se hai molto tempo e vuoi ascoltare un programma radiofonico italiano su tecnologia, spazio e cose simili con molta musica, il mio programma è chiamato “Katzenjammer” ogni lunedì, a partire dalle 20:00 fuso orario Europa/Roma.

Ci sono anche i podcast 😀

https://www.radiocittaperta.it/podcast/utenti-in-pericolo-su-facebook-meta-e-il-pianeta-rosso-katzenjammer-del-20-dicembre/

Forse condividerò alcuni dettagli tecnici e il codice in un post futuro, comunque non esitare a contattarmi per dettagli o domande

Convertire i video per vederli sulla Playstation 3 / PS3

So che scaricare e convertire video è una procedura vecchio stile che, al momento, sembra inutile e dispendiosa in termini di tempo. Ma la mia PlayStation 3 funziona ancora a meraviglia e posso guardare un film mentre sono seduto sul divano usando il controller come telecomando, quindi molto meglio di un computer sulle mie gambe connesso a un sito Web di streaming.

Una posizione non comoda per vedere de film

Il problema è che la PS3, PlayStation 3, riproduce solo alcuni tipi di file e molto spesso è necessario convertire i file scaricati in un formato adatto. Dopo aver cercato su Google e guardato intorno, ho finalmente trovato le mie impostazioni perfette. Prima di tutto, devi usare ffmpeg per convertire il file. ffmpeg è uno strumento super potente che può fare un sacco di cose con video e audio. Lo useremo per convertire il file di input in un formato che può essere riprodotto da PS3. Supponiamo di avere un file denominato

INPUT_FILE_NAME.mkv

(.mkv è un formato che PS3 non può riprodurre) Quindi, per convertirlo basta usare questo comando:

ffmpeg -y -i "INPUT_FILE_NAME.mkv" -vf scale=1024:-1 -c:v libx264 -pix_fmt nv12 -acodec aac -b:a 192k -ac 2 -ar 44100 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" -f mp4 "OUTPUT_FILE_NAME.mp4"

Se odi il doppiaggio (so che ci sono molti amanti del cinema che odiano il doppiaggio, io non sono uno di loro, a dire il vero) puoi anche mettere il sottotitolo che è (spesso) nel file .mkv scaricato, direttamente in l’mp4 in uscita. Sfortunatamente, non puoi disabilitarlo, ma è un buon compromesso. In questo caso, usa questo comando

ffmpeg -y -i "INPUT_FILE_NAME.mkv" -vf scale=1024:-1 -c:v libx264 -pix_fmt nv12 -vf subtitles="INPUT_FILE_NAME.mkv":si=0 -acodec aac -b:a 192k -ac 2 -ar 44100 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" -f mp4 "OUTPUT_FILE_NAME.mp4" > /dev/null 2>&1 < /dev/null &

Dove ho solo aggiunto la parte

-vf subtitles="INPUT_FILE_NAME.mkv":si=0

che sostanzialmente dice a ffmpeg di “ottenere i sottotitoli dal file di input, ottenere la prima traccia dei sottotitoli, numero 0, e renderli nel file di output”. Puoi cambiare il nome del file e, finché ffmpeg può leggere il file di input, avrai un file utilizzabile dalla tua PS3. Un’altra opzione che ho aggiunto è il > /dev/null 2>&1 < /dev/null & alla fine del comando in modo che venga eseguito in background.

La prima parte > /dev/null 2>&1 fondamentalmente dice a ffmpeg di non mettere alcun output da nessuna parte.

La seconda parte < /dev/null dice a ffmpeg che non c’è input interattivo (sì, ffmpeg è uno strumento interattivo!)…

… e l’ultima parte & signifca “gira in background“!

 

Ti è piaciuto questo articolo? Considera una donazione!