Arti Zirk - Syncly MusicSync: Difference between revisions
First edit |
|||
(7 intermediate revisions by the same user not shown) | |||
Line 5: | Line 5: | ||
[https://github.com/Syncly Syncly MusicSync] on minu Java<ref>[https://itcollege.ois.ee/et/subject/view?subject_id=51&year=2015 I200]</ref> kodu töö. | [https://github.com/Syncly Syncly MusicSync] on minu Java<ref>[https://itcollege.ois.ee/et/subject/view?subject_id=51&year=2015 I200]</ref> kodu töö. | ||
Tegu on üsnagi <abbr title="Keep It Simple Stupid">KISS</abbr> teenusega mis võimaldab kasutajal sünkroniseerida YouTube keskonnas olevaid playliste helifailidena enda telefoni. | Tegu on üsnagi <abbr title="Keep It Simple Stupid">KISS</abbr> teenusega mis võimaldab kasutajal sünkroniseerida YouTube keskonnas olevaid playliste helifailidena enda telefoni. | ||
== Idee == | |||
Õues ringi jalutades või rattaga sõites meeldib mulle kõrvaklapid pähe pannes muusikat kuulata. Tavaliselt on minu muusika allikaks YouTube üles laetud lood mis on mul playlisti lisatud ning mida ma siis aegaajalt ühe väikese scriptiga enda arvuti ja sealt edasi telefoni tõmban. [http://rg3.github.io/youtube-dl/ youtube-dl] on üks väike pythonis kirjutatud programm mis oskab seda väga hästi teha. | |||
<pre> | |||
#!/bin/bash | |||
youtube-dl -i -x --download-archive .archive.txt -f bestaudio "http://www.youtube.com/playlist?list=PLB5VrND_o3PgZNzNdohFDWE5BTFIPDImQ" | |||
adb push -p * /sdcard/Music/ | |||
</pre> | |||
Mu sõber Mark tegi selle automaatse sünkroniseerimis osa isegi ära enamvähem ning lükkas koodi githubi üles nightsnack<ref>[https://github.com/mikroskeem/nightsnack nightsnack]</ref> nimega aga see ei lahenda ära lugude telefoni saamis probleemi. | |||
Sügisel algas Java progemis kursus mille raames otsutasin Javas kirjutatud Androidi rakenduse teha mis oskaks minu lugusi automaatselt telefoni tõmmata. | |||
== Planeering == | |||
Kõigepealt alustasin Androidi platvormi dokumentatsiooni lugemisega ja üritasin enamvähem paika panna mida ma androidi rakenduses kuvada tahaksin ning tegin endale enamvähem selgeks kuidas Androidi poolt ära teostada. | |||
Selle lõpptulemuseks on midagi sellist | |||
[[File:MusicSync_home.png|320px]][[File:MusicSync_settings.png|320px]] | |||
Edasi panin paika punktid mida mul oleks vaja et backend server teeks: | |||
* Playlistide kuvamine / lisamine / eemaldamine | |||
* Playlistides olevate lugude kuvamine | |||
* Teadete genereerimine playlisti lugude lisamise/eemaldamise korral | |||
== Tehnoloogiate valik == | |||
Backend serveri kirjutamiseks tuli teha valik kuidas ma täpselt selle ära lahendan kasutades mis asju. | |||
Playlistide ja seal olevate lugude salvestamiseks otsustasin kasutada [https://www.mongodb.org/ MongoDB] andmebaasi mis on üks NoSQL andmebaas JSON sarnaste dokumentide salvestamiseks. Valisin MongoDB just selle pärast, et olen seda varasemalt kasutanud, arenduse käigus andmestruktuuri muutmine on üli kerge ning kuna SQL pole mulle eriti kunagi meeldinud. | |||
YouTubest lugude allalaadimiseks hetkel ainuke laialt toetatud varjant on kasutada youtube-dl pythoni programmi. On olemas ka erinevaid veebilehti mis oskavad YouTubest alla laadida helifaile aga ka need suuretõenäosusega kasutavad midagi sarnast tagaplaanil. Kuna youtube-dl on kirjutatud Pythonis siis on selle kasutamine Pythoni scriptides kergem ja annab rohkem võimalusi selle käitumise muutmiseks kui mõne muu lahenduse kasutamine. | |||
Kuna mu arti.ee serverist pole eriti palju kettapinda, et sinna ka muusika ära mahutada siis otsustasin kasutada [https://aws.amazon.com/s3/ Amazon S3] pilveservereid kuhu Youtubest allalaetud muusika paigutada ning sealt neid vajadusel telefoni tõmmata. | |||
Genereeritud teadete edastamiseks sobib mulle väga hästi [https://github.com/wandenberg/nginx-push-stream-module nginx-push-stream-module] mis võimaldab kergesti genereerida Server Sent Events striimi mida on võimalik töödelda väga kergelt kõigi programeerimis keeltega ja veebilehitsejatel on sse tarbimise jaoks sisseehitatud tugi javascriptis. | |||
HTTP API ehitamiseks, mille kaudu teha päringuid serveri pihta, otsustasin teha kasutades Pythoni teeki nimega [http://falconframework.org/ Falcon]. Falcon on minimaalne Pythoni <abbr title="Web Server Gateway Interface">WSGI</abbr> liidest täitev teek HTTP [https://en.wikipedia.org/wiki/Representational_state_transfer RESTful] api'de tegemiseks. Siin on näide sellst kui ilus lõpptulemus jääb kasutades Falconit https://gist.github.com/artizirk/ae9cf28d1f45ef0aa965 | |||
== Backendi implementeerimine == | |||
Alustasin Youtube playlisti videote lisamise ja eemaldamise eventide genereerimisega. Selleks otsustasin ära kasutada youtube-dl sisse ehitatud funktsionaalsust mis annab mulle tagasi nimekirja lugudest mis on playlistis | |||
Hetkel siis on mul üks <code>playlist-sync.py</code> fail kus on while True loop mis iga andmebaasi lisatud playlisti kohta käivitab <code>get_song_updates</code> meetodi. <code>get_song_updates</code> meetod omakorda tõmbab alla, kasutades youtube-dl teeki, ette antud youtube playlisti html lehe ning ekstraktib sealt kõigi lugude id'd ning ka lugude nimed. Peale seda kui mul on käes list loo id-ga, küsin ma andmebaasist kas need lood on juba lisatud, kui pole, lisan selle ning genereerin evendi. Selleks et teada saada kas mõni lugu on kustutatud playlistis käin ma kõik andmebaasi lisatud antud playlisti lood läbi ning testin kas nad on eelnevalt alla tõmmatud lugude listis, kui pole siis genereerin evendi et lugu on kustutatud youtube playlistist. | |||
<code>youtube-downloader.py</code> skript kuulab eelnevalt genereeritud evente ning lugude lisamise korral tõmbab nad alla youtube-dl teegi abil ja laeb nad Amazon S3'e üles kasutades boto3 teeki. | |||
<code>api.py</code> hoolitseb HTTP API eest. | |||
Hetkel implementeerib http api neli endpointi kuhu pihta on võimalik päringuid teha | |||
* <code>/playlists/</code> - kollektsioon playlistidest | |||
* <code>/playlists/{playlist_id}</code> - üks kindel playlist | |||
* <code>/playlists/{playlist_id}/songs/</code> - kollektsioon lugudest ühes playlistis | |||
* <code>/playlists/{playlist_id}/songs/{song_id}</code> - üks kindel lugu | |||
Iga see url on implementeeritud erineva klasssi poolt mis omakorda pärinevad <code>BaseResponse</code> klassist ning kõik nad tagastavad andmeid json vormingus | |||
paar näidet hetkel implementeeritud api kohta | |||
<pre>% # Küsime serveri lisatud playlistid | |||
% http GET http://localhost:8000/playlists | |||
HTTP/1.0 200 OK | |||
Date: Tue, 08 Dec 2015 13:16:33 GMT | |||
Server: WSGIServer/0.2 CPython/3.5.0 | |||
content-length: 202 | |||
content-type: application/json; charset=utf-8 | |||
[ | |||
{ | |||
"_id": "PLGE39Wpa-qf1xjp4gmJ_1PBzH7a_-GdOe", | |||
"title": "Nice Music [WIP]", | |||
"type": "YoutubePlaylist" | |||
}, | |||
{ | |||
"_id": "PLB5VrND_o3PgZNzNdohFDWE5BTFIPDImQ", | |||
"title": "Music I like", | |||
"type": "YoutubePlaylist" | |||
} | |||
] | |||
</pre> | |||
<pre>% # Küsime mis lood on ühes playlistis | |||
% http GET http://localhost:8000/playlists/PLB5VrND_o3PgZNzNdohFDWE5BTFIPDImQ/songs | |||
HTTP/1.0 200 OK | |||
Date: Tue, 08 Dec 2015 13:17:01 GMT | |||
Server: WSGIServer/0.2 CPython/3.5.0 | |||
content-length: 546 | |||
content-type: application/json; charset=utf-8 | |||
[ | |||
{ | |||
"_id": "qFDP9egTwfM", | |||
"deleted": false, | |||
"playlist": "PLB5VrND_o3PgZNzNdohFDWE5BTFIPDImQ", | |||
"title": "Netsky - Rio (Official Video) ft. Digital Farm Animals", | |||
"type": "Youtube", | |||
"url": "http://s3.storage.ms.wut.ee/qFDP9egTwfM" | |||
}, | |||
{ | |||
"_id": "FGBhQbmPwH8", | |||
"deleted": false, | |||
"playlist": "PLB5VrND_o3PgZNzNdohFDWE5BTFIPDImQ", | |||
"title": "Daft Punk - One More Time", | |||
"type": "Youtube", | |||
"url": "http://s3.storage.ms.wut.ee/FGBhQbmPwH8" | |||
} | |||
] | |||
</pre> | |||
Kokkuvõttes on ülesehitus midagi sellist: | |||
[[File:MusicSync_chart.png|500px]] | |||
== Androidi klient == | |||
Nüüd kus backend osa on valmis on mul võimalik Androidi rakendus ka ära lõpetada. | |||
Kui kunagi peaksin selle valmis saama siis viskan siia ka kirjelduse selle kohta ja uuendan esitlust. | |||
== Raha == | |||
Kuna serverid maksavad, peale minu on veel inimesi kes on näidanud huvi selle teenuse kasutamise vastu ja ma ise enda taskust ka kõike kinni ei taha maksta siis otsustasin selle tasuliseks teenuseks teha teistele. | |||
Hetkel on plaan küsida selle teenuse eest 1€ kuus mis tähendab, et mul oleks vaja vähemalt 10 inimest kes püsivalt maksaks et ma oma Amazon S3 ja DigitalOceanis oleva serveri tasudega nulli saaks. | |||
Amazon S3 maksab hetkel 0.03€/GB ja 0.1€ eest saab seal hoida ~3GB jagu andmeid, failide tõmbamine maksab 0.09€/GB nii et kogu muusikakogu 3GB alla laadimine maksab 0.27€ mis omakorda tähendab et DigitalOceani serveri maksmiseks jääb 0.63€. DigitalOceani server maksab mulle hetkel 6€/kuus mis siis lõpuks teebki, et vähemalt 10 pidevalt maksvat kasutajat vaja et asi nulli tuleks rahaliselt. Iga järgmine kasutaja hakkab sisse tooma mulle umbes 0.6€ kuus. | |||
See kõik on muidugi eeldusel, et kasutajad keskmiselt väga palju muusikat üles ei lae. | |||
== Legaalne pool == | |||
Youtube Terms of Service ei luba tegelikuses nende lehelt videosi alla laadida ning neid vaadata/kuulata mujal kui youtube enda lehel ja youtube rakenduses. | |||
https://www.youtube.com/terms lehel olev tekst teeb selle üsna selgeks nii, et üsna riskantne värk oleks mul seda musicsync asja suureks ajada. Paar kümmend inimest peaks okei olema ja mitte väga palju tähelepanu äratama. | |||
= Viited = | = Viited = | ||
{{Reflist}} | {{Reflist}} |
Latest revision as of 22:47, 9 December 2015
Esitlus
Esitluse slaidid on siin: http://slides.com/artizirk/musicsync
Syncly MusicSync
Syncly MusicSync on minu Java[1] kodu töö. Tegu on üsnagi KISS teenusega mis võimaldab kasutajal sünkroniseerida YouTube keskonnas olevaid playliste helifailidena enda telefoni.
Idee
Õues ringi jalutades või rattaga sõites meeldib mulle kõrvaklapid pähe pannes muusikat kuulata. Tavaliselt on minu muusika allikaks YouTube üles laetud lood mis on mul playlisti lisatud ning mida ma siis aegaajalt ühe väikese scriptiga enda arvuti ja sealt edasi telefoni tõmban. youtube-dl on üks väike pythonis kirjutatud programm mis oskab seda väga hästi teha.
#!/bin/bash youtube-dl -i -x --download-archive .archive.txt -f bestaudio "http://www.youtube.com/playlist?list=PLB5VrND_o3PgZNzNdohFDWE5BTFIPDImQ" adb push -p * /sdcard/Music/
Mu sõber Mark tegi selle automaatse sünkroniseerimis osa isegi ära enamvähem ning lükkas koodi githubi üles nightsnack[2] nimega aga see ei lahenda ära lugude telefoni saamis probleemi.
Sügisel algas Java progemis kursus mille raames otsutasin Javas kirjutatud Androidi rakenduse teha mis oskaks minu lugusi automaatselt telefoni tõmmata.
Planeering
Kõigepealt alustasin Androidi platvormi dokumentatsiooni lugemisega ja üritasin enamvähem paika panna mida ma androidi rakenduses kuvada tahaksin ning tegin endale enamvähem selgeks kuidas Androidi poolt ära teostada.
Selle lõpptulemuseks on midagi sellist
Edasi panin paika punktid mida mul oleks vaja et backend server teeks:
- Playlistide kuvamine / lisamine / eemaldamine
- Playlistides olevate lugude kuvamine
- Teadete genereerimine playlisti lugude lisamise/eemaldamise korral
Tehnoloogiate valik
Backend serveri kirjutamiseks tuli teha valik kuidas ma täpselt selle ära lahendan kasutades mis asju.
Playlistide ja seal olevate lugude salvestamiseks otsustasin kasutada MongoDB andmebaasi mis on üks NoSQL andmebaas JSON sarnaste dokumentide salvestamiseks. Valisin MongoDB just selle pärast, et olen seda varasemalt kasutanud, arenduse käigus andmestruktuuri muutmine on üli kerge ning kuna SQL pole mulle eriti kunagi meeldinud.
YouTubest lugude allalaadimiseks hetkel ainuke laialt toetatud varjant on kasutada youtube-dl pythoni programmi. On olemas ka erinevaid veebilehti mis oskavad YouTubest alla laadida helifaile aga ka need suuretõenäosusega kasutavad midagi sarnast tagaplaanil. Kuna youtube-dl on kirjutatud Pythonis siis on selle kasutamine Pythoni scriptides kergem ja annab rohkem võimalusi selle käitumise muutmiseks kui mõne muu lahenduse kasutamine.
Kuna mu arti.ee serverist pole eriti palju kettapinda, et sinna ka muusika ära mahutada siis otsustasin kasutada Amazon S3 pilveservereid kuhu Youtubest allalaetud muusika paigutada ning sealt neid vajadusel telefoni tõmmata.
Genereeritud teadete edastamiseks sobib mulle väga hästi nginx-push-stream-module mis võimaldab kergesti genereerida Server Sent Events striimi mida on võimalik töödelda väga kergelt kõigi programeerimis keeltega ja veebilehitsejatel on sse tarbimise jaoks sisseehitatud tugi javascriptis.
HTTP API ehitamiseks, mille kaudu teha päringuid serveri pihta, otsustasin teha kasutades Pythoni teeki nimega Falcon. Falcon on minimaalne Pythoni WSGI liidest täitev teek HTTP RESTful api'de tegemiseks. Siin on näide sellst kui ilus lõpptulemus jääb kasutades Falconit https://gist.github.com/artizirk/ae9cf28d1f45ef0aa965
Backendi implementeerimine
Alustasin Youtube playlisti videote lisamise ja eemaldamise eventide genereerimisega. Selleks otsustasin ära kasutada youtube-dl sisse ehitatud funktsionaalsust mis annab mulle tagasi nimekirja lugudest mis on playlistis
Hetkel siis on mul üks playlist-sync.py
fail kus on while True loop mis iga andmebaasi lisatud playlisti kohta käivitab get_song_updates
meetodi. get_song_updates
meetod omakorda tõmbab alla, kasutades youtube-dl teeki, ette antud youtube playlisti html lehe ning ekstraktib sealt kõigi lugude id'd ning ka lugude nimed. Peale seda kui mul on käes list loo id-ga, küsin ma andmebaasist kas need lood on juba lisatud, kui pole, lisan selle ning genereerin evendi. Selleks et teada saada kas mõni lugu on kustutatud playlistis käin ma kõik andmebaasi lisatud antud playlisti lood läbi ning testin kas nad on eelnevalt alla tõmmatud lugude listis, kui pole siis genereerin evendi et lugu on kustutatud youtube playlistist.
youtube-downloader.py
skript kuulab eelnevalt genereeritud evente ning lugude lisamise korral tõmbab nad alla youtube-dl teegi abil ja laeb nad Amazon S3'e üles kasutades boto3 teeki.
api.py
hoolitseb HTTP API eest.
Hetkel implementeerib http api neli endpointi kuhu pihta on võimalik päringuid teha
/playlists/
- kollektsioon playlistidest/playlists/{playlist_id}
- üks kindel playlist/playlists/{playlist_id}/songs/
- kollektsioon lugudest ühes playlistis/playlists/{playlist_id}/songs/{song_id}
- üks kindel lugu
Iga see url on implementeeritud erineva klasssi poolt mis omakorda pärinevad BaseResponse
klassist ning kõik nad tagastavad andmeid json vormingus
paar näidet hetkel implementeeritud api kohta
% # Küsime serveri lisatud playlistid % http GET http://localhost:8000/playlists HTTP/1.0 200 OK Date: Tue, 08 Dec 2015 13:16:33 GMT Server: WSGIServer/0.2 CPython/3.5.0 content-length: 202 content-type: application/json; charset=utf-8 [ { "_id": "PLGE39Wpa-qf1xjp4gmJ_1PBzH7a_-GdOe", "title": "Nice Music [WIP]", "type": "YoutubePlaylist" }, { "_id": "PLB5VrND_o3PgZNzNdohFDWE5BTFIPDImQ", "title": "Music I like", "type": "YoutubePlaylist" } ]
% # Küsime mis lood on ühes playlistis % http GET http://localhost:8000/playlists/PLB5VrND_o3PgZNzNdohFDWE5BTFIPDImQ/songs HTTP/1.0 200 OK Date: Tue, 08 Dec 2015 13:17:01 GMT Server: WSGIServer/0.2 CPython/3.5.0 content-length: 546 content-type: application/json; charset=utf-8 [ { "_id": "qFDP9egTwfM", "deleted": false, "playlist": "PLB5VrND_o3PgZNzNdohFDWE5BTFIPDImQ", "title": "Netsky - Rio (Official Video) ft. Digital Farm Animals", "type": "Youtube", "url": "http://s3.storage.ms.wut.ee/qFDP9egTwfM" }, { "_id": "FGBhQbmPwH8", "deleted": false, "playlist": "PLB5VrND_o3PgZNzNdohFDWE5BTFIPDImQ", "title": "Daft Punk - One More Time", "type": "Youtube", "url": "http://s3.storage.ms.wut.ee/FGBhQbmPwH8" } ]
Kokkuvõttes on ülesehitus midagi sellist:
Androidi klient
Nüüd kus backend osa on valmis on mul võimalik Androidi rakendus ka ära lõpetada. Kui kunagi peaksin selle valmis saama siis viskan siia ka kirjelduse selle kohta ja uuendan esitlust.
Raha
Kuna serverid maksavad, peale minu on veel inimesi kes on näidanud huvi selle teenuse kasutamise vastu ja ma ise enda taskust ka kõike kinni ei taha maksta siis otsustasin selle tasuliseks teenuseks teha teistele.
Hetkel on plaan küsida selle teenuse eest 1€ kuus mis tähendab, et mul oleks vaja vähemalt 10 inimest kes püsivalt maksaks et ma oma Amazon S3 ja DigitalOceanis oleva serveri tasudega nulli saaks.
Amazon S3 maksab hetkel 0.03€/GB ja 0.1€ eest saab seal hoida ~3GB jagu andmeid, failide tõmbamine maksab 0.09€/GB nii et kogu muusikakogu 3GB alla laadimine maksab 0.27€ mis omakorda tähendab et DigitalOceani serveri maksmiseks jääb 0.63€. DigitalOceani server maksab mulle hetkel 6€/kuus mis siis lõpuks teebki, et vähemalt 10 pidevalt maksvat kasutajat vaja et asi nulli tuleks rahaliselt. Iga järgmine kasutaja hakkab sisse tooma mulle umbes 0.6€ kuus.
See kõik on muidugi eeldusel, et kasutajad keskmiselt väga palju muusikat üles ei lae.
Legaalne pool
Youtube Terms of Service ei luba tegelikuses nende lehelt videosi alla laadida ning neid vaadata/kuulata mujal kui youtube enda lehel ja youtube rakenduses. https://www.youtube.com/terms lehel olev tekst teeb selle üsna selgeks nii, et üsna riskantne värk oleks mul seda musicsync asja suureks ajada. Paar kümmend inimest peaks okei olema ja mitte väga palju tähelepanu äratama.