Arti Zirk - Syncly MusicSync: Difference between revisions

From ICO wiki
Jump to navigationJump to search
(Veel teksti)
Line 45: Line 45:


== Backendi implementeerimine ==
== Backendi implementeerimine ==
TODO
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>


= Viited =
= Viited =
{{Reflist}}
{{Reflist}}

Revision as of 16:33, 8 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"
    }
]

Viited