milaq / YCast

Self hosted vTuner internet radio service emulation
Other
243 stars 93 forks source link

Add support for radio-browser.info #4

Closed Zenith-Nadir closed 4 years ago

Zenith-Nadir commented 5 years ago

I was wondering how feasible, it would be to modify Ycast script to access http://radio-browser.info database, either locally (having nginx running it) or directly through the original internet website, for browsing radio stations by similar features/categories as those being fazed out from Yamaha AVRs (and I guess other AVRs as well) vTuner service? Sincerely, Z-N

milaq commented 5 years ago

Sounds like a good idea; they even have a solid JSON API.

If I find some freetime I'll definitely have a closer look at it.

milaq commented 5 years ago

Working on it...

milaq commented 5 years ago

First steps are done. If you want, you can try it out (here be dragons) and kindly report your experience back.

https://github.com/milaq/YCast/tree/dev

Zenith-Nadir commented 5 years ago

Hi Micha, Thanks for your work and advancements. I have a question: before I had to run ycast.py script, and now, which one: vtuner, radiobrowser? Z-N

milaq commented 5 years ago

As this is (almost) a Python module now, you can run it via python -m ycast if you are inside the main directory.

Alternatively, you can also just execute __main__.py in the ycast subdirectory.

Zenith-Nadir commented 5 years ago

Hi Micha, I am not sure what I am doing wrong, or Not doing. Before setting nginx, I just wanted to execute ycast, and with previous version, I get server listening on port. But here, with the dev branch I get errors: User@Ubuntu:~/Downloads/YCast-dev$ python -m ycast -p 8010 Traceback (most recent call last): File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main "main", fname, loader, pkg_name) File "/usr/lib/python2.7/runpy.py", line 72, in _run_code exec code in run_globals File "/home/User/Downloads/YCast-dev/ycast/main.py", line 6, in from ycast import server File "ycast/server.py", line 4, in from flask import Flask, request, url_for ImportError: No module named flask User@Ubuntu:~/Downloads/YCast-dev$ cd /home/User/Downloads/YCast-dev/ycast User@Ubuntu:~/Downloads/YCast-dev/ycast$ ./main.py -p 8010 Traceback (most recent call last): File "./main.py", line 6, in from ycast import server ModuleNotFoundError: No module named 'ycast' User@Ubuntu:~/Downloads/YCast-dev/ycast$ python --version Python 2.7.15+ User@Ubuntu:~/Downloads/YCast-dev/ycast$ python3 --version Python 3.6.8 User@Ubuntu:~/Downloads/YCast-dev/ycast$ python3 ./main.py -p 8010 Traceback (most recent call last): File "./main.py", line 6, in from ycast import server ModuleNotFoundError: No module named 'ycast' User@Ubuntu:~/Downloads/YCast-dev/ycast$ cd .. User@Ubuntu:~/Downloads/YCast-dev$ python3 -m ycast -p 8010 Traceback (most recent call last): File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main "main", mod_spec) File "/usr/lib/python3.6/runpy.py", line 85, in _run_code exec(code, run_globals) File "/home/User/Downloads/YCast-dev/ycast/main.py", line 6, in from ycast import server File "/home/User/Downloads/YCast-dev/ycast/server.py", line 4, in from flask import Flask, request, url_for ModuleNotFoundError: No module named 'flask' What should I do to fix this and make ycast working? Z-N

milaq commented 5 years ago

The dev version requires flask. I should've mentioned that.

pip install flask should get rid of the error.

The packaged version will automatically pull in requirements in the future.

Zenith-Nadir commented 5 years ago

Hi Micha, This is what I am experiencing so far:

  1. I installed flask.
  2. When I change into top ycast directory, and using python without specifying python3 I get service running. With python3 I get errors.
  3. I am unable to install it as a service. Following master version, I am getting errors and failures to run it as systemd service, so temporarily, I do run it manually.
  4. I managed to set it and run it on nginx. I get webpage.
  5. On Yamaha receiver, I get menu: Radiobrowser and My Stations. On Radiobrowser, I get: Genres, Countries, and Most Popular. Going to either Genres or Countries I get only first page. Next pages return me to top menu Radiobrowser. Also in Genres or countries the first page selections, when selecting a category it tells loading and returns to top Radiobrowser selection. Yamaha tells successfully connected to network. I wanted to add that when browsing nginx webpage I get listings up to stations in a country. I also tried master version of ycast and it lists radio stations from the list and plays them. So, I guess, nginx is talking to radio-browser web site, but Yamaha API somehow has problems with the current code.

Z-N

milaq commented 5 years ago

Hey mate, thanks for the feedback and sorry for the delay. It was a busy week.

I went ahead and implemented vTuner API paging (see https://github.com/milaq/YCast/commit/1123f3e55b9fa196c69db5fd5b0b4c3c7261eeca).

This should (or could) get rid of the issue you are describing.

Regarding the installation procedure: I will put together a proper readme when things are implemented and tested.

Can you test the latest dev branch please? https://github.com/milaq/YCast/tree/dev

Thanks and cheers

Zenith-Nadir commented 5 years ago

Hi Micha, Now, with these changes: Much Better! But... in the countries section, plenty of countries do not list (It looks, like those with low stations count), eg Monaco, Mauritius, Monte Carlo, etc. I was able to browse by genre and most popular, which are from most clicks (not most votes) section on web site. Still not able to run as systemd service, but you explained. Also, how do you My Stations section get to work? I don't think on the web site there is anything like this, to bookmark favorites or my stations. And, where could I change setting for ycast to look for my local radiobrowser server on my local nginx, not published on internet. This is a great, fantastic job so far. Kudos and thank you! Update: Ok, so I managed to change how countries and stations are displayed: I modified radiobrowser.py file and changed MINIMUMS to value 0 (zero), so all countries are displayed. I change limit of bitrate to 16, since there are some stations with very low bitrate (I spotted as low as 24kbps); also increased value station limit of 1000 to 100000, but this might be limited by Yamaha API vtuner code, I will test it some other time. I have noticed that stations are displayed in entry ID order, and NOT alphanumerically or in alphabetic order. Also, countries with non-standard western characters cause: ACCESS ERROR. Characters as &, Ö, greek, cyrillic in countries names, however in stations names there is no problem. Not sure if it is Yamaha API limit or python code Also, some stations play on web, but will not on Yamaha. I suspect it might be url of https, and not http-this also remains to be tested. Update2: Ok, it seems like Yamaha does NOT like secure https urls. The same station with http url plays a stream, but the one with https-does NOT. Update3: So, I have managed to get stations lists, in countries and genres, sorted in standard ascending alphabetical order, by modifying radiobrowser.py and there in get_stations_by_country & get_stations_by_genre, stations_json = request('stations/search?order=votes&reverse=true&bitrateMin=', changing values to: stations/search?order=name&reverse=false So far, so good :) Z-N

milaq commented 5 years ago

Hey, thanks for your response and thorough writeup, that's really helping me alot.

in the countries section, plenty of countries do not list (It looks, like those with low stations count), eg Monaco, Mauritius, Monte Carlo, etc.

This is to filter bogus countries. Some countries aren't real countries or have typos. We can assume that a country with a very low station count match that category.

Also, how do you My Stations section get to work? I don't think on the web site there is anything like this, to bookmark favorites or my stations.

Same as before, but you need to specify your stations.yml with -c.

I change limit of bitrate to 16, since there are some stations with very low bitrate (I spotted as low as 24kbps)

This is to penalize station owners which only send with a very low bitrate. In 2019 we can expect anyone to be able to stream with at least 64kbit. This also filters bogus stations as explained above.

Ok, it seems like Yamaha does NOT like secure https urls. The same station with http url plays a stream, but the one with https-does NOT.

Yeah, I noticed that with the station logos. For now I implemented a basic http strip filter (only for station urls, not logos). See https://github.com/milaq/YCast/commit/83ad5733eda78c2ce7b46a7bf89e99b0c0d267f5

So, I have managed to get stations lists, in countries and genres, sorted in standard ascending alphabetical order

Thanks, I corrected that here: https://github.com/milaq/YCast/commit/1e9cc568f4aa329fe6f86f720571e63fd7378321

also increased value station limit of 1000 to 100000, but this might be limited by Yamaha API vtuner code, I will test it some other time.

I changed it so it doesn't limit the results apart from the 'Votes' section (see https://github.com/milaq/YCast/commit/ae9f168e8b99da6328d73773917b93ee43a8c2d9). We need to keep an eye on that though, so it doesn't crash AVRs which do not utilise paging.

I'll be looking into the issue with the logos and characters. Thanks again and cheers

Zenith-Nadir commented 5 years ago

Hi Micha, Thanks for your great work and fantastic progress. ---There however, in stations/search?order=name&reverse=true statement, reverse=true HAS TO BE CHANGED TO FALSE, otherwise the sorting is in reversed order from Z to A, and there are no means to manipulate these records through Yamaha interface. ---Regarding stripping https that is a great attempt, hopefully it will work, as long as broadcasters provide http protocol as well, and not exclusively https. ---Regarding other thoughts you expressed, I want to keep the radio db as clean as possible (since it is on my private nginx server), but with as many entries as there are available. Bitrate I do understand for USA or Western Europe broadcasters, but what about Third World Countries-they can only use resources available there, so I will keep all stations regarding of bitrate. Regarding number of entries, per country, applies similar, there are locations with 1 or 2 stations only, and they would get excluded (and they might not be bogus at all, but perfectly legit). Anyway, if I spot some other way to improve ycast and its interaction with radio-browser, I will let you know.


UPDATE_as of Jul-23-2019 10:00 AM CEDT(-Central European Daylight Saving Time :) )

---Https stripping WORKS! perfectly-Micha you are genius! ---I wanted to let you know on my Yamaha RX-V773 m3u8 playlists and urls pointing to those do NOT work (I think it is Yamaha), not sure about other tuners. ---m3u work and pls playlists some do some do not (I was not checking if this was because there was no http link or just format of pls. TuneIn pls worked at least in one case.


UPDATE_as of Jul-31st-2019 9:50 AM CEDT(-Central European Daylight Saving Time) Regarding stations icons, so far I was able to find only one displaying: German station MDR Klassik. No other icons, even those with http:// url would show up. Not sure what it depends on (size of the icon, link), so far I did not find any correlation. ---This would bring me to ask you a question: is there any way to display those radiobrowser stations in an app on Ubuntu, sort-of-emulating Yamaha radio API? Just to speed up some testing.


UPDATE_as of Aug-4th-201911:10 AM CEDT(-Central European Daylight Saving Time) I have noticed a very strange weird behavior for some stations, and this is probably somehow releted to icons (not sure why it would, but it is): All stations are of the group: OpenFM - (Poland; all Polish stations). When they are in My Stations list (which is yml playlist w/o icons links), they play w/o any issues, when in Radio-Browser, every single one freezes/crashes Yamaha API. Every single one from this group. I have tried to change logo icon size, but to no avail-no help. However, when I delete favicon link (it is my local home nginx server db), it stops crashing the app, and plays as it normally would. Very weird behavior, but I just wanted to report it to you.


UPDATE_as of Aug-5th-2019 12:00 NOON CEDT(-Central European Daylight Saving Time) RE: Unicode UTF-8 characters in country names and custom station names: I have did some more research and would like to report some of my findings and errors: ---Current flask seems to run on python 2.7. There does not seem to be a python3 ver available in this project as yet. According to google searches, supposedly python3 resolves string and unicode issues without modifying the code. ---Now regarding unicode characters in countries names, I get following error:

2019-08-05 09:18:56 ERROR: Exception on /ycast/radiobrowser/country/Türkmenistan [GET] Traceback (most recent call last): File "/home/user/.local/lib/python2.7/site-packages/flask/app.py", line 2446, in wsgi_app response = self.full_dispatch_request() File "/home/user/.local/lib/python2.7/site-packages/flask/app.py", line 1951, in full_dispatch_request rv = self.handle_user_exception(e) File "/home/user/.local/lib/python2.7/site-packages/flask/app.py", line 1820, in handle_user_exception reraise(exc_type, exc_value, tb) File "/home/user/.local/lib/python2.7/site-packages/flask/app.py", line 1949, in full_dispatch_request rv = self.dispatch_request() File "/home/user/.local/lib/python2.7/site-packages/flask/app.py", line 1935, in dispatch_request return self.view_functionsrule.endpoint File "ycast/server.py", line 151, in radiobrowser_country_stations stations = radiobrowser.get_stations_by_country(directory) File "ycast/radiobrowser.py", line 83, in get_stations_by_country str(MINIMUM_BITRATE) + '&countryExact=true&country=' + str(country)) UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 1: ordinal not in range(128) 2019-08-05 09:18:56 INFO: 127.0.0.1 - - [05/Aug/2019 09:18:56] "GET /ycast/radiobrowser/country/Türkmenistan?mac=0000000001000000B42C&fver=W&dlang=eng&startitems=1&enditems=10 HTTP/1.0" 500 - <<<<< The symbol ampersand "&", does cause error, but does not show any errors in terminal console. ---Now in the custom stations My Stations file, if there are unicode characters I get access error with the following error in terminal console:

2019-08-05 11:35:30 ERROR: Exception on /ycast/my_stations/Favorite Stations [GET] Traceback (most recent call last): File "/home/user/.local/lib/python2.7/site-packages/flask/app.py", line 2446, in wsgi_app response = self.full_dispatch_request() File "/home/user/.local/lib/python2.7/site-packages/flask/app.py", line 1951, in full_dispatch_request rv = self.handle_user_exception(e) File "/home/user/.local/lib/python2.7/site-packages/flask/app.py", line 1820, in handle_user_exception reraise(exc_type, exc_value, tb) File "/home/user/.local/lib/python2.7/site-packages/flask/app.py", line 1949, in full_dispatch_request rv = self.dispatch_request() File "/home/user/.local/lib/python2.7/site-packages/flask/app.py", line 1935, in dispatch_request return self.view_functionsrule.endpoint File "ycast/server.py", line 124, in custom_stations_category for station in sorted(my_stations[category], key=str.lower): TypeError: descriptor 'lower' requires a 'str' object but received a 'unicode' 2019-08-05 11:35:30 INFO: 127.0.0.1 - - [05/Aug/2019 11:35:30] "GET /ycast/my_stations/Favorite%20Stations?mac=0000000001000000B42C&fver=W&dlang=eng&startitems=1&enditems=10 HTTP/1.0" 500 - <<<<< I have googled and found a remedy to replace str.lower to unicode.lower, but this did NOT work. So, at this moment I am getting rid of any unicode characters, but as long-term it might not be feasible since it is international multilanguage database. I hope there will be a solution to resolve these issues soon.

BUT: see below & again: Thank You Micha


Nevertheless, I still do love how it works now, I do not need to rely anymore on not-working-anymore vTuner service Thanks. Sincerely, Z-N

segler-alex commented 5 years ago

hi, i am the developer of www.radio-browser.info if you need any help, or have any suggestions feel free to contact me. thank you for this project, i myself own a yamaha receiver :)

milaq commented 5 years ago

@Zenith-Nadir: Many thanks again for your extensive testing and writeup. You are a great assistance for these issues. I have opened new issues for the station icons and playlist support you mentioned. See https://github.com/milaq/YCast/issues/9 and https://github.com/milaq/YCast/issues/10. I'll have a look at that. Regarding the unicode formatting errors: Can you test the latest dev branch and see if it resolves that? If this was an issue with the ampersand, it should be resolved with https://github.com/milaq/YCast/commit/f10110dc9207a937cd30e78f8e832f26219edac5.

@segler-alex: Hey mate, first off: Thanks for creating such an awesome project. The API is very well documented and works just nicely. Good to hear you are potentially profiting from YCast yourself with your hardware :+1: If I have any in-depth questions I'd refer to your kind offer of assistance. Thanks and cheers

Zenith-Nadir commented 5 years ago

Hi Micha, I will test the changes. Ampersand "&" was working once I switched to python3 and flask using python3. BUT, in the meantime, before your changes I made some updates to radiobrowser.py and server.py files regarding languages, which are working very well, and I paste these changes here. Sorry, I do not know who to put it in GitHub for comparison and review.

---File: radiobrowser.py

  1. UNDER LINE WITH: MINIMUM_COUNT_COUNTRY = (as I mentioned before, not to set any limits, I set this value to ZERO (0)) MINIMUM_COUNT_LANGUAGE = 0

  2. UNDER SECTION: def get_countries(): ... return countries I SET SECTION: (indicated between lines)


    def get_languages(): languages = [] languages_raw = request('languages') for language_raw in languages_raw: if get_json_attr(language_raw, 'name') and get_json_attr(language_raw, 'stationcount') and \ int(get_json_attr(language_raw, 'stationcount')) > MINIMUM_COUNT_LANGUAGE: languages.append(get_json_attr(language_raw, 'name')) return languages


  3. UNDER SECTION: def get_stations_by_country(country): ... return stations I SET SECTION: (indicated between lines)


def get_stations_by_language(language): stations = [] stations_json = request('stations/search?order=name&reverse=false&bitrateMin=' + str(MINIMUM_BITRATE) + '&languageExact=true&language=' + str(language)) for station_json in stations_json: stations.append(Station(station_json)) return stations



---File: server.py

PATH_RADIOBROWSER_GENRE = 'genre'

PATH_RADIOBROWSER_LANGUAGE = 'language' PATH_RADIOBROWSER_POPULAR = 'popular'


SECTION: @app.route('/' + PATH_ROOT + '/' + PATH_RADIOBROWSER + '/') def radiobrowser_landing(): page = vtuner.Page() page.add(vtuner.Previous(url_for('landing', _external=True))) page.add(vtuner.Directory('Genres', url_for('radiobrowser_genres', _external=True))) page.add(vtuner.Directory('Countries', url_for('radiobrowser_countries', _external=True))) page.add(vtuner.Directory('Languages', url_for('radiobrowser_languages', _external=True))) page.add(vtuner.Directory('Most Popular', url_for('radiobrowser_popular', _external=True))) page.add(vtuner.Search('Search', url_for('radiobrowser_search', _external=True, path=''))) return page.to_string()


SECTION below definition for COUNTRY:

@app.route('/' + PATH_ROOT + '/' + PATH_RADIOBROWSER + '/' + PATH_RADIOBROWSER_LANGUAGE + '/') def radiobrowser_languages(): directories = radiobrowser.get_languages() return get_directories_page('radiobrowser_language_stations', directories, request.args.get('startitems'), request.args.get('enditems')).to_string()

@app.route('/' + PATH_ROOT + '/' + PATH_RADIOBROWSER + '/' + PATH_RADIOBROWSER_LANGUAGE + '/') def radiobrowser_language_stations(directory): stations = radiobrowser.get_stations_by_language(directory) return get_stations_page(stations, request.args.get('startitems'), request.args.get('enditems')).to_string()

Zenith-Nadir commented 5 years ago

Hi Micha, UPDATE_as of Aug-12th-2019 18:00 CEDT(-Central European Daylight Saving Time) TEST RESULTS after the most recent changes from 2 hours ago. I had to revert vTuner.py and server.py to previous versions (they work nicely with language additions changes I mentioned above in my previous post above). main.py shows incorrect python version, but after its message, it hangs in terminal w/o returning to a cmd prompt. But I left this file in my current ycast settings. After using new vTuner and Server files, I cannot browse My Stations. It literally restarts NetRadio app on Yamaha RX-V773, reconnects tuner app to network. When reverting vTuner file only, I can browse My Stations, but Radiobrowser Countries and Languages show only first screen (Letter "A"), and this is entire selection. So, I am back to previous vTuner and Server files. I hope this will provide some light and info. Sincerely, Z-N

milaq commented 4 years ago

I'll close this issue now, as most of the functionality has been implemented in the dev branch (https://github.com/milaq/YCast/tree/dev) and there are no major issues left besides the ones listed separately.