Gambas-it

Gambas3 => Programmazione => Topic aperto da: allegfede - 15 Novembre 2017, 17:45:57

Titolo: [RISOLTO] trovare la cover art di un brano
Inserito da: allegfede - 15 Novembre 2017, 17:45:57
salve a tutti.

Come forse sapete sto' portando avanti il progetto di una regia radiofonica automatica completamente open source e il prototipo sta' gia' girando da un paio di mesi senza grossi problemi (PRS personal radio station su source forge).

Il sottosistema audio e' jack e utilizzando questo posso avere il segnale d'uscita che viene inviato sulla LAN dal pc di play, catturato da un raspberry pi2 e trasformato in un segnale adatto ad essere inviato ai trasmettitori FM (con RDS e stereo elaborati vi software in tempo reale dal PI).

Sempre con Jack, sono riuscito a passare il segnale d'uscita della mia regia automatica a due encoder:
darkice per lo streaming su internet (ogg vorbis 48kbps)
odr-dab enc per fornire l'audio ad un multiplex DAB (radio digitale via etere) speriementale.

La cosa divertente e' che posso fornire (il software e' mio, posso mandare i dati dove voglio :D) sia all'RDS (della vecchia FM) sia all'encoder DAB, il nome della canzone e l'autore/esecutore del brano (o se e' in onda il radio giornale o altri metadati) e questi vengono riprodotti dalle autoradio opportunamente capaci.

Ora pero' volevo mandare ANCHE la cover art (la copertina) del brano che si sta' ascoltando (od una grafica opportuna per le news, logo del programma, etc.) ma ho un problema.

COME TROVARE la copertina del brano?

So che e' possibile fare una cosa del genere:
eyeD3 --write-images=DIR mp3_file

ma spesso i file mp3 o altro formato NON hanno la copertina.

Pensavo di appoggiarmi a google images o meglio ad un servizio come questo:
https://coverartarchive.org/
https://archive.org/details/coverartarchive

C'e' qualcuno che ha voglia di sbattersi a fare un modulo che da "artista","album" estragga l'immagine e la sbatta da qualche parte?

per esempio ho visto che cercando la cover degli iron maiden (album powerslave) la stringa che il browser passa al server e':
https://archive.org/details/coverartarchive?and[]=iron%20maiden%20powerslave&and[]=mediatype%3A%22image%22

pero' ritorna una pagina dei risultati ed andrebbe estratta una delle immagini .... e sinceramente la parte web non mi piace per nulla ....

PS:stavo anche pensando che, essendo il recover delle imamgini un processo lento, farlo ogni volta che si manda in play un brano non ha senso ... sarebbe meglio fare un comando da lanciare batch e fargli aggiungere le cover a tutti i brani nel DB (ma a questo ci potrei pensare io).

Detto questo, vi manterro' informati sull'evoluzione del progetto :D
Titolo: Re:trovare la cover art di un brano
Inserito da: allegfede - 15 Novembre 2017, 17:51:52
ci sarebbe anche una API per far questo .. ma .... la programmazione WEB non mi e' mai piaciuta ....

https://musicbrainz.org/doc/Cover_Art_Archive/API
Titolo: Re:trovare la cover art di un brano
Inserito da: allegfede - 15 Novembre 2017, 18:42:37
forse ci siamo .. almeno per la prima parte del discorso.
Con questo codice riesco a scaricare una pagina web dal sito opportuno. Ma non e' la pagina giusta :-(

Codice: [Seleziona]
' Gambas class file

Public Covers As Collection[] 'collezione di tutte le risposte json

Public StringaRicerca As String

Public StringaRisultati As String[]

Public MyHttpClient As New HttpClient As "ClienteHTTP"

Public Result As File


Public Sub Button_Search_Click()
Dim server As String = "https://archive.org/details/coverartarchive"
  'per esempio https://archive.org/details/coverartarchive?and[]=iron%20maiden%20powerslave&and[]=mediatype%3A%22image%22
  'StringaRicerca = "https://archive.org/details/coverartarchive?and[]=" & webalize(TextBox_Autore.Text) & "%20" & webalize(TextBox_Album.Text) & "&and[]=mediatype%3A%22image%22"
  StringaRicerca = "?and[]=" & webalize(TextBox_Autore.Text) & "%20" & webalize(TextBox_Album.Text) & "&and[]=mediatype%3A%22image%22"
 
  MyHttpClient.URL = server

  MyHttpClient.Post("application/json", StringaRicerca,, User.Home & "/result.html")
  'result = MyHttpClient.Post("application/json", StringaRicerca)
 
End

Public Function webalize(stringa As String) As String
 
  stringa = Replace(stringa, " ", "%20")
 
  Return stringa
End

Public Sub ClienteHTTP_read()
 
  Debug "legge qualcosa"

End

Public Sub ClienteHTTP_Finished()
 
  'Debug Result.Save(User.Home & "/risultati.html")
  Debug "fine lettura"
End

Ovvero e' una pagina del CoverArchive, ma sembra ignorare la mia richiesta ....

Come faccio a capire quale stringa invia il post?
Titolo: Re:trovare la cover art di un brano
Inserito da: allegfede - 15 Novembre 2017, 18:48:10
passando da post a get ci siamo:

Codice: [Seleziona]
Public Sub Button_Search_Click()

  'per esempio https://archive.org/details/coverartarchive?and[]=iron%20maiden%20powerslave&and[]=mediatype%3A%22image%22
  StringaRicerca = "https://archive.org/details/coverartarchive?and[]=" & webalize(TextBox_Autore.Text) & "%20" & webalize(TextBox_Album.Text) & "&and[]=mediatype%3A%22image%22"
 
  MyHttpClient.URL = StringaRicerca
 
  MyHttpClient.get(, User.Home & "/result_get.html")
End

ora devo fare il parsing della pagina e trovare dove sta' il file di immagine :D
Titolo: Re:trovare la cover art di un brano
Inserito da: allegfede - 15 Novembre 2017, 20:29:11
in allegato un piccolo esempio MOOOLTO didattico che funziona (su un caso particolare, andrebbe testato piu' in generale su album diversi) al 90%

estrae l'url del file immagine vero e proprio, se mettiamo questo url in un browser si vede la copertina ... ma non la scarica .... (sara' che non gestisce file binari?)

Titolo: Re:trovare la cover art di un brano
Inserito da: vuott - 16 Novembre 2017, 00:25:52
si vede la copertina ... ma non la scarica ....

Sospetto che il problema risieda in quel " https "
Titolo: Re:trovare la cover art di un brano
Inserito da: Gianluigi - 16 Novembre 2017, 11:30:22
Sospetto che il problema risieda in quel " https "

 :ciao:  Allegfede,

non so se può servire, ma potresti dare un'occhiata al componente gb.desktop desktop open e al componente gb.web application protocol.
Titolo: Re:trovare la cover art di un brano
Inserito da: allegfede - 16 Novembre 2017, 12:26:13
Non penso sia un problema dell'httpS.

Le altre pagine erano tutte https ma le ha scaricate senza problemi.

Penso sia un problema legato al MIME type. Il testo standard probabilemente lo prende di default senza bisogno di specificare, nel caso delle jpeg invece bisognera' passargli un mime type opportuno, ma in get non so come si fa' ....

MyHttpClient3.post("image/jpeg", etc etc ....,

l'ho trasformato in get cosi':

MyHttpClient3.get(["image/jpeg"], User.Home & "/copertina.jpg")

ho anche provato a rimpiazzare https con normale http:
MyHttpClient3.URL = Replace(Label_CoverPath.Text, "https", "http")

ma mi crea sempre un file di 0 byte ....
Titolo: Re:trovare la cover art di un brano
Inserito da: allegfede - 16 Novembre 2017, 12:56:58
SVELATO L'ARCANO!!!

scaricando il file da questa path:
"https://archive.org/download/mbid-6ed7b940-99b2-3e8f-b624-114cc96165f4/mbid-6ed7b940-99b2-3e8f-b624-114cc96165f4-17000904511.jpg"

in realta' il server di archive.org risponde con REDIRECT che nel browser web diventa:
"https://ia600607.us.archive.org/12/items/mbid-6ed7b940-99b2-3e8f-b624-114cc96165f4/mbid-6ed7b940-99b2-3e8f-b624-114cc96165f4-17000904511.jpg"

quindi in realta' sto' scaricando la pagina del redirect e non il vero e proprio file jpeg .....

passando l'url vero FINALE la scarica perfettamente con:
MyHttpClient3.get(["image/jpeg"], User.Home & "/copertina.jpg")

..... indi per cui devo analizzare questo redirect ed intercettare la vera path ....
Titolo: Re:trovare la cover art di un brano
Inserito da: allegfede - 16 Novembre 2017, 13:23:46
HELP tra libreria in C:
https://github.com/metabrainz/libcoverart

o Java:
https://github.com/lastfm/coverartarchive-api

con quale mi impicco?
Titolo: Re:trovare la cover art di un brano
Inserito da: Gianluigi - 16 Novembre 2017, 13:52:20
SVELATO L'ARCANO!!!
:ok:
HELP tra libreria in C:
https://github.com/metabrainz/libcoverart

o Java:
https://github.com/lastfm/coverartarchive-api

con quale mi impicco?

Nella speranza dell'aiuto di qualcuno (uno a caso...  ;D) io opterei per la prima.

 :ciao:
Titolo: Re:trovare la cover art di un brano
Inserito da: vuott - 16 Novembre 2017, 14:10:27
io opterei per la prima.


Esattamente, perché Gambas - come ormai è arcinoto - può gestire direttamente le funzioni esterne delle librerie, scritte in C, attraverso la parola-chiave Extern.

Della libreria "coverart " dovrai utilizzare i prototipi delle funzioni esterne dichiarate nel file d'intestazione " /usr/include/coverart/caa_c.h ", wrapper C, tenuto conto che la libreria è scritta invece in C++ .
Titolo: Re:trovare la cover art di un brano
Inserito da: allegfede - 16 Novembre 2017, 17:00:21
una supercazzola in pratica ...  :rotfl: :rotfl:

Codice: [Seleziona]
' Gambas class file

Library "coverart"  'libreria di musicbrainz per la gestione delle locandine
Extern FetchImage(id As String) As Picture  'la funzione C++ sarebbe std::vector<unsigned char> ImageData=CoverArt.FetchImage(ReleaseID,Image->ID());

.......
Public Sub Button_Download_Click()
Dim copertina As Image

  copertina = FetchImage(Replace(label_IdAlbum.Text, "mbid-", ""))

   ....


cannot find dynamic library 'coverart.so' ... etc etc
Titolo: Re:trovare la cover art di un brano
Inserito da: vuott - 16 Novembre 2017, 18:42:55
Codice: [Seleziona]
library "coverart"

cannot find dynamic library 'coverart.so' ... etc etc
...dove sei andato a prenderla quella libreria "coverart" ?!   ???



Titolo: Re:trovare la cover art di un brano
Inserito da: allegfede - 16 Novembre 2017, 18:45:18
e' che non ti capisco :D

parli una lingua aliena :D

allora forse dovrei usare:
Extern caa_coverart_fetch_front(CaaCoverArt CoverArt, const char * ReleaseID);

ma come gli passo la chiave? come recupero l'imamgine?
Extern caa_coverart_fetch_front(CoverArt As Picture, ReleaseID As String)
oppure:
Extern caa_coverart_fetch_front(ReleaseID As String) As Picture
Titolo: Re:trovare la cover art di un brano
Inserito da: vuott - 16 Novembre 2017, 18:47:25

Extern FetchImage(id As String) As Picture  'la funzione C++ sarebbe std::vector<unsigned char> ImageData=CoverArt.FetchImage(ReleaseID,Image->ID());

In quale file header sta dichiarato questo prototipo della funzione esterna ?     ???
Titolo: Re:trovare la cover art di un brano
Inserito da: vuott - 16 Novembre 2017, 18:55:44
Ad ogni modo la libreria che dovresti usare è questa:

/usr/lib/x86_64-linux-gnu/libcoverart.so.1.0.0


Il file d'intestazione contenente le varie funzioni scritte in C è il seguente:

/usr/include/coverart/caa_c.h
Titolo: Re:trovare la cover art di un brano
Inserito da: vuott - 16 Novembre 2017, 18:59:38
allora forse dovrei usare:
Extern caa_coverart_fetch_front(CaaCoverArt CoverArt, const char * ReleaseID);
Eh, ...appunto !




ma come gli passo la chiave? come recupero l'imamgine?
Extern caa_coverart_fetch_front(CoverArt As Picture, ReleaseID As String)

...e che ne so io ?   :rotfl:


Ho trovato 'sto esempio (non so se ti può essere utile  :-\ ):
https://github.com/metabrainz/libcoverart/blob/master/examples/example_c.c
Titolo: Re:trovare la cover art di un brano
Inserito da: vuott - 16 Novembre 2017, 19:09:15
Extern caa_coverart_fetch_front(CoverArt As Picture, ReleaseID As String)

Attenzione: il C è una cosa e Gambas è un'altra cosa.
Il C non conosce il tipo "Picture".

Il prototipo di questa funzione esterna è:

CaaImageData caa_coverart_fetch_front(CaaCoverArt CoverArt, const char *ReleaseID)

laddove:

- CaaCoverArt  è dichiarato come un Puntatore generico (a void);
- const char * è sostanzialmente quello che in Gambas chiamiamo tipo "String";
- CaaImageData  è dichiarato come un Puntatore generico (a void).


La variabile di tipo Puntatore presente nel primo parametro formale (ossia: CaaCoverArt CoverArt) la ottieni - preliminarmente - da quest'altra funzione esterna:
CaaCoverArt caa_coverart_new(const char *UserAgent)
Titolo: Re:trovare la cover art di un brano
Inserito da: allegfede - 17 Novembre 2017, 20:44:54
allora, con l'aiuto di un simpatico utente di musicBrainz (nell'apposito forum), sono riuscito un'altra volta a non cedere alle lusinghe del C e del buon Vuott (che ci mete il cuore lo so  a cercare di farmi imparare :D).

Il trucco era analizzare gli HEADER del socket HTTP.

in caso di temporary redirect (307, ma a me spesso da anche un 302) il sito ritorna la posizione reale di stoccaggio della copertina ....

In allegato il progetto didattico (nella realta' verra' generato l'evento e tutto andra' in cascata).

grazie :D