{"id":15980831,"url":"https://github.com/macbre/now-playing-graph","last_synced_at":"2025-07-14T08:32:38.430Z","repository":{"id":141987982,"uuid":"168988314","full_name":"macbre/now-playing-graph","owner":"macbre","description":"Processes \"now playing\" data from internet radio player for Faroese Útvarp","archived":false,"fork":false,"pushed_at":"2019-02-11T20:42:50.000Z","size":1038,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-05T05:26:39.584Z","etag":null,"topics":["faroe","graph","music","playlist-parser","python37","radio-player"],"latest_commit_sha":null,"homepage":"https://macbre.github.io/now-playing-graph/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/macbre.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-03T20:10:38.000Z","updated_at":"2019-02-11T20:42:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"1686cea8-9f3b-426d-89ec-7f673eaed88a","html_url":"https://github.com/macbre/now-playing-graph","commit_stats":{"total_commits":55,"total_committers":2,"mean_commits":27.5,"dds":"0.036363636363636376","last_synced_commit":"2c211ef5544a6892e8e5fc2556ffcc6b7ca7ab84"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/macbre/now-playing-graph","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macbre%2Fnow-playing-graph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macbre%2Fnow-playing-graph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macbre%2Fnow-playing-graph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macbre%2Fnow-playing-graph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/macbre","download_url":"https://codeload.github.com/macbre/now-playing-graph/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macbre%2Fnow-playing-graph/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265262615,"owners_count":23736429,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["faroe","graph","music","playlist-parser","python37","radio-player"],"created_at":"2024-10-08T00:23:04.851Z","updated_at":"2025-07-14T08:32:38.402Z","avatar_url":"https://github.com/macbre.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# now-playing-graph\n![](https://raw.githubusercontent.com/macbre/now-playing-graph/master/docs/graph.png)\n\nProcesses \"now playing\" data from [internet radio player](https://kvf.fo/popout/widget) for [Faroese Útvarp](https://kvf.fo/forsida/english).\n\n## Requirements\n\n**Python 3.7 is required** because [`datetime.datetime.fromisoformat` is used](https://docs.python.org/dev/library/datetime.html#datetime.datetime.fromisoformat).\n\n## Why?\n\nAs a fan of all Faroese aspects, I'm curious to know:\n\n* which artist is most frequently played?\n* which artist songs are played for the the longest time?\n* is some artist typically followed by another one?\n\n## Collecting the data\n\nThe following bash script is run every minute to scrape \"now playing\" data from kvf.fo site:\n\n```bash\ncurl -s --max-time 3 'https://netvarp.kringvarp.fo:80/sse' 2\u003e\u00261  | grep data \u003e\u003e ~/kvf.log\n```\n\n## Data model\n\n\"Now playing\" stream is turned into a graph with two types of nodes (modeled after [schema.org types](https://schema.org/)):\n\n### Band / artist\n\u003e https://schema.org/MusicGroup\n\n* `name`\n\n### Song\n\u003e https://schema.org/MusicRecording\n\n* `byArtist` -\u003e a graph's edge linking to band / artist\n* `duration`([ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations), e.g. `PT6M33S`)\n* `name`\n\n## Statistics\n\n```\n$ get_stats\n2019-02-11 21:41:47 render_graph         INFO     Going to parse a stream from /home/macbre/src/git/now-playing-graph/data/kvf.log.gz\n2019-02-11 21:41:47 root                 INFO     Lines parsed: 21959\n2019-02-11 21:41:47 render_graph         INFO     Got a timeline with 2197 entries\ntop_artists: [('Eyðun Nolsøe', 16), ('Marius Ziska', 16), ('Streaplers', 14), ('Jens Marni Hansen', 14), ('Blátt Gras', 13), ('Ole Ivars', 13), ('Dalia Ouziel,  Gil Sharon,  Ron Ephrat,  Etc.', 12), ('Contrazt', 12), ('Dænsebændet', 12), ('Lasse Stefanz', 12)]\n\ntop_songs: [('Lukkan er ei gullið', 10), ('Á tíni slóð', 9), ('Eitt lítið tár í tøgnini', 9), ('Einsemi', 8), ('Heima er saman við tær', 7), ('Lieder Ohne Worte No. 3 in G Minor, Op. 53: Presto Agitato', 6), ('Samrøða fjalla millum', 6), (\"Bahib'm'bau (kom við)\", 6), ('Leingist so', 6), ('Piano Concerto in A Minor, Op. 7: I. Allegro Maestoso', 6)]\n\nlongest_songs: [('Symphony in C minor I. Allegro molto', 844), ('Mendelssohn: Piano Sextet In D, Op. 110 - 1. Allegro Vivace', 773), ('4th Symphony - 3.Il tempo largo', 720), ('Mendelssohn: Piano Sextet In D, Op. 110 - 4. Allegro Vivace', 694), ('Trombone Concerto, Op.81 - 2. satsur Andante', 662), ('Piano Trio In G Minor, Op. 17: I. Allegro Moderato', 633), ('Heljareyga', 613), ('Periferi', 605), ('4th Symphony - 1.Tempo molto moderato, quasi adagio', 598), ('4th Symphony - 4.Allegro', 564)]\n\nlongest_artists: [('Ilona Prunyi', 2433), ('Gothenburg Symphony Orchestra cond. Okko Kamu, Cond.: Okko Kamu', 2210), ('Berliner Philharmoniker - Herbert von Karajan', 2168), ('Marius Ziska', 2097), ('Ólavur á Váli', 2044), ('Hannis', 1996), ('Dalia Ouziel,  Gil Sharon,  Ron Ephrat,  Etc.', 1952), ('Stockholm Sinfonietta,  Neemi Jærvi stjórnar', 1869), ('Streaplers', 1745), ('Moyzeskvartettin', 1620)]\n```\n\n## Data examples\n\nHere's the snippet of collected data:\n\n```json\ndata: {\"updated\":\"2019-01-22T20:27:23.930\",\"now\":{\"artist\":\"Jasmin\",\"title\":\"Make Sense\",\"start\":\"2019-01-22T20:27:22.318\"},\"next\":{\"artist\":\"Teitur\",\"title\":\"I Want to Be Kind\",\"start\":\"2019-01-22T20:31:36.810\"}}\ndata: {\"updated\":\"2019-01-22T20:31:37.973\",\"now\":{\"artist\":\"Teitur\",\"title\":\"I Want to Be Kind\",\"start\":\"2019-01-22T20:31:36.113\"},\"next\":{\"artist\":\"Hamradun\",\"title\":\"Ein stutt og stokkut løta\",\"start\":\"2019-01-22T20:35:45.775\"}}\ndata: {\"updated\":\"2019-01-22T20:31:37.973\",\"now\":{\"artist\":\"Teitur\",\"title\":\"I Want to Be Kind\",\"start\":\"2019-01-22T20:31:36.113\"},\"next\":{\"artist\":\"Hamradun\",\"title\":\"Ein stutt og stokkut løta\",\"start\":\"2019-01-22T20:35:45.775\"}}\ndata: {\"updated\":\"2019-01-22T20:31:37.973\",\"now\":{\"artist\":\"Teitur\",\"title\":\"I Want to Be Kind\",\"start\":\"2019-01-22T20:31:36.113\"},\"next\":{\"artist\":\"Hamradun\",\"title\":\"Ein stutt og stokkut løta\",\"start\":\"2019-01-22T20:35:45.775\"}}\ndata: {\"updated\":\"2019-01-22T20:31:37.973\",\"now\":{\"artist\":\"Teitur\",\"title\":\"I Want to Be Kind\",\"start\":\"2019-01-22T20:31:36.113\"},\"next\":{\"artist\":\"Hamradun\",\"title\":\"Ein stutt og stokkut løta\",\"start\":\"2019-01-22T20:35:45.775\"}}\ndata: {\"updated\":\"2019-01-22T20:35:42.473\",\"now\":{\"artist\":\"Hamradun\",\"title\":\"Ein stutt og stokkut løta\",\"start\":\"2019-01-22T20:35:40.614\"},\"next\":{\"artist\":\"Frændur\",\"title\":\"Uttanumtos\",\"start\":\"2019-01-22T20:38:26.234\"}}\ndata: {\"updated\":\"2019-01-22T20:35:42.473\",\"now\":{\"artist\":\"Hamradun\",\"title\":\"Ein stutt og stokkut løta\",\"start\":\"2019-01-22T20:35:40.614\"},\"next\":{\"artist\":\"Frændur\",\"title\":\"Uttanumtos\",\"start\":\"2019-01-22T20:38:26.234\"}}\ndata: {\"updated\":\"2019-01-22T20:35:42.473\",\"now\":{\"artist\":\"Hamradun\",\"title\":\"Ein stutt og stokkut løta\",\"start\":\"2019-01-22T20:35:40.614\"},\"next\":{\"artist\":\"Frændur\",\"title\":\"Uttanumtos\",\"start\":\"2019-01-22T20:38:26.234\"}}\ndata: {\"updated\":\"2019-01-22T20:38:19.440\",\"now\":{\"artist\":\"Frændur\",\"title\":\"Uttanumtos\",\"start\":\"2019-01-22T20:38:17.833\"},\"next\":{\"artist\":\"Wolfgang\",\"title\":\"Ice Cold\",\"start\":\"2019-01-22T20:41:45.936\"}}\ndata: {\"updated\":\"2019-01-22T20:38:19.440\",\"now\":{\"artist\":\"Frændur\",\"title\":\"Uttanumtos\",\"start\":\"2019-01-22T20:38:17.833\"},\"next\":{\"artist\":\"Wolfgang\",\"title\":\"Ice Cold\",\"start\":\"2019-01-22T20:41:45.936\"}}\ndata: {\"updated\":\"2019-01-22T20:38:19.440\",\"now\":{\"artist\":\"Frændur\",\"title\":\"Uttanumtos\",\"start\":\"2019-01-22T20:38:17.833\"},\"next\":{\"artist\":\"Wolfgang\",\"title\":\"Ice Cold\",\"start\":\"2019-01-22T20:41:45.936\"}}\ndata: {\"updated\":\"2019-01-22T20:41:47.483\",\"now\":{\"artist\":\"Wolfgang\",\"title\":\"Ice Cold\",\"start\":\"2019-01-22T20:41:45.668\"},\"next\":{\"artist\":\"Fróði Bjarnason\",\"title\":\"Where My Home Is\",\"start\":\"2019-01-22T20:44:46.528\"}}\n```\n\n`kvf_stream_to_timeline` helper will turn the above stream into a list of `TimelineEntry` dataclasses:\n\n```python\nTimelineEntry(artist_name='Jasmin', song_title='Make Sense', duration=254, played_at=datetime.datetime(2019, 1, 22, 20, 27, 22, 318000))\nTimelineEntry(artist_name='Teitur', song_title='I Want to Be Kind', duration=249, played_at=datetime.datetime(2019, 1, 22, 20, 31, 36, 113000))\nTimelineEntry(artist_name='Hamradun', song_title='Ein stutt og stokkut løta', duration=165, played_at=datetime.datetime(2019, 1, 22, 20, 35, 40, 614000))\nTimelineEntry(artist_name='Frændur', song_title='Uttanumtos', duration=208, played_at=datetime.datetime(2019, 1, 22, 20, 38, 17, 833000))\nTimelineEntry(artist_name='Wolfgang', song_title='Ice Cold', duration=180, played_at=datetime.datetime(2019, 1, 22, 20, 41, 45, 668000))\n```\n\n`timeline_to_models` helper will give you a set of models with songs linking back to artists:\n\n```\n\u003cArtistModel https://schema.org/MusicGroup (Eivør Pálsdóttir) songs = \"3\"\u003e\n\u003cArtistModel https://schema.org/MusicGroup (Enekk) songs = \"2\"\u003e\n\u003cArtistModel https://schema.org/MusicGroup (Orka) songs = \"1\"\u003e\n\u003cSongModel https://schema.org/MusicRecording (Elisabeth og Elinborg) duration = \"253\"\u003e\n\t--[:byArtist]-\u003e(Eivør Pálsdóttir)\n\u003cSongModel https://schema.org/MusicRecording (Mannabarn) duration = \"292\"\u003e\n\t--[:byArtist]-\u003e(Eivør Pálsdóttir)\n\u003cSongModel https://schema.org/MusicRecording (Vársins ljóð) duration = \"274\"\u003e\n\t--[:byArtist]-\u003e(Eivør Pálsdóttir)\n\u003cSongModel https://schema.org/MusicRecording (Slatur) duration = \"195\"\u003e\n\t--[:byArtist]-\u003e(Enekk)\n\u003cSongModel https://schema.org/MusicRecording (Ódn) duration = \"268\"\u003e\n\t--[:byArtist]-\u003e(Enekk)\n\u003cSongModel https://schema.org/MusicRecording (Hon leitar) duration = \"132\"\u003e\n\t--[:byArtist]-\u003e(Orka)\n```\n\n`models_to_graph_json` helper will then return [GraphJSON](https://github.com/jsongraph/json-graph-specification) representation of the timeline:\n\n```json\n{\n \"nodes\": [\n  {\n   \"id\": \"5834d4db6\",\n   \"caption\": \"Eiv\\u00f8r P\\u00e1lsd\\u00f3ttir\",\n   \"type\": \"MusicGroup\"\n  },\n  {\n   \"id\": \"51e2d554b\",\n   \"caption\": \"Enekk\",\n   \"type\": \"MusicGroup\"\n  },\n  {\n   \"id\": \"5705c4343\",\n   \"caption\": \"Orka\",\n   \"type\": \"MusicGroup\"\n  },\n  {\n   \"id\": \"1d12586d0\",\n   \"caption\": \"Elisabeth og Elinborg\",\n   \"type\": \"MusicRecording\"\n  },\n  {\n   \"id\": \"dccf0f42d\",\n   \"caption\": \"Mannabarn\",\n   \"type\": \"MusicRecording\"\n  },\n  {\n   \"id\": \"51b04a795\",\n   \"caption\": \"V\\u00e1rsins lj\\u00f3\\u00f0\",\n   \"type\": \"MusicRecording\"\n  },\n  {\n   \"id\": \"308f8a2b4\",\n   \"caption\": \"Slatur\",\n   \"type\": \"MusicRecording\"\n  },\n  {\n   \"id\": \"bef2f5fc9\",\n   \"caption\": \"\\u00d3dn\",\n   \"type\": \"MusicRecording\"\n  },\n  {\n   \"id\": \"b73add98e\",\n   \"caption\": \"Hon leitar\",\n   \"type\": \"MusicRecording\"\n  }\n ],\n \"edges\": [\n  {\n   \"source\": \"1d12586d0\",\n   \"target\": \"5834d4db6\",\n   \"caption\": \"byArtist\"\n  },\n  {\n   \"source\": \"dccf0f42d\",\n   \"target\": \"5834d4db6\",\n   \"caption\": \"byArtist\"\n  },\n  {\n   \"source\": \"51b04a795\",\n   \"target\": \"5834d4db6\",\n   \"caption\": \"byArtist\"\n  },\n  {\n   \"source\": \"308f8a2b4\",\n   \"target\": \"51e2d554b\",\n   \"caption\": \"byArtist\"\n  },\n  {\n   \"source\": \"bef2f5fc9\",\n   \"target\": \"51e2d554b\",\n   \"caption\": \"byArtist\"\n  },\n  {\n   \"source\": \"b73add98e\",\n   \"target\": \"5705c4343\",\n   \"caption\": \"byArtist\"\n  }\n ]\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacbre%2Fnow-playing-graph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmacbre%2Fnow-playing-graph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacbre%2Fnow-playing-graph/lists"}