lossless1024 / StreaMonitor

Adult live stream downloader for advanced people. I could have chosen a better name.
GNU General Public License v3.0
177 stars 44 forks source link

Set resolution #23

Closed maddi4u closed 1 year ago

maddi4u commented 1 year ago

How to set custom resolution to record streams in 720p or 480p or 1080p

DerBunteBall commented 1 year ago

Actually not possible. It's statically in bot.py (should decide the best available) and the Downloader actually not supports general options.

Eventually @lossless1024 sets this to TODO List.

Best Regards

lossless1024 commented 1 year ago

It is possible I think, however there are sites where there is only one resolution. But definitely need some rework.

maddi4u commented 1 year ago

Was asking because videos took a lot of space. Will manage.

ThEnGI commented 1 year ago

Actually not possible. It's statically in bot.py (should decide the best available) and the Downloader actually not supports general options.

Wanting to use only one resolution, which line should I change?. eg. 720p streams only

DerBunteBall commented 1 year ago

Wanting to use only one resolution, which line should I change?. eg. 720p streams only

You would need to modify getBestSubPlaylist (begins at line 139 in bot.py).

It figures the best Playlist out of an m3u8. Keep in mind that site extractors can pass postition argument to that method.

Best Regards

ThEnGI commented 1 year ago

more help? I'm not good at python, I tried changing the "position" parameter no effect is something easy or do I have to redo the whole function?

Thanks in advance T

DerBunteBall commented 1 year ago

It's not that simple to change it.

The easiest but really dirty solution is the following:

You could install the m3u8 extension pip3 install m3u8 in your virtual environment and try my crappy reimplementation of the function:

def getBestSubPlaylist(url, position):
    try:
        wanted_resolution = "1280x720"
        sources = {}
        result = requests.get(url)
        m3u8_doc = result.content.decode("utf-8")
        variant_m3u8 = m3u8.loads(m3u8_doc)
        if variant_m3u8.is_variant:
            for playlist in variant_m3u8.playlists:
                sources[str(playlist.stream_info.resolution[0])+"x"+str(playlist.stream_info.resolution[1])] = playlist.uri
            if sources[wanted_resolution].startswith("https://"):
                return sources[wanted_resolution]
            else:
                return '/'.join(url.split('.m3u8')[0].split('/')[:-1]) + '/' + sources[wanted_resolution]
        else:
            return None
    except:
        return None

This should return the 720p chunklist URL. You could wrap this in a little script to test it. wanted_resolution follows the resolution format width x height so 1080p would be 1920x1080. Keep in mind that the script doesn't check whether the set resolution exists. A non existing one should give a None back because it throws an exception. Keep in mind that the Bot wouldn't tell you that. Also import m3u8 like this:

import m3u8

Just a dirty hack and not tested in StreaMonitor source. Use at own risk. URL loading of m3u8 seems to be really unhappy with much stuff so I had only working results by converting to string in a prior step and throw it in as a string. position argument needs to be present as argument to don't break the function signature used in other parts. Also self needs to stay present becasue it's a class method.

Best Regards

ThEnGI commented 1 year ago

Thanks for the dedicated time! I tried it on CB with 720p and 480p resolution, it seems to do the opposite of what you said: there are too many streams and it can't choose...... joking aside, from a first search it seems that there is a problem with the variable "position" which is passed more then one time

Anyway this error:

ERROR - [CB] alison_lu: getBestSubPlaylist() got multiple values for argument 'position'
Traceback (most recent call last):
     File "/home/XXX/StreaMonitor/streamonitor/bot.py", line 123, in run
         self.getVideo(self, self.getVideoUrl(), self.genOutFilename())
     File "/home/XXX/StreaMonitor/streamonitor/sites/chaturbate.py", line 15, in getVideoUrl 
         return self.getBestSubPlaylist(self.lastInfo['url'], position=-1)
TypeError: getBestSubPlaylist() got multiple values for argument 'position'

Could the error be in the getBestSubPlaylist function call on line 14 of the chaturbate.py file? in which "position" is set to -1

Sorry I'm not too helpful :-(

Edit: sometimes Download.py hangs in the closing phase and I have to kill it. however it seems to stop all downloads correctly. It's not a priority

You are very quick to answer, know that I am in no hurry! Thanks again

DerBunteBall commented 1 year ago

Tested in StreaMonitor code with a CB model.

Actually it's not possible to declare different resolutions for models. So you need to decide which you want. If you set wanted_resolution to 1280x720 you will always get 720p for all extractors who call this function. The position argument is simply ignored.

Check this gist (https://gist.github.com/DerBunteBall/3b8c65c39c543312716c2d036ef4b2fa) to see how the file should look. Gives 720p files when adding and starting a CB model.

You need to set the resolution in the class method so it's not configurable by a file or so. It's really dirty.

Short note: ffmpeg Downlaoder thorws a funny exception but starts ffmpeg on Python 3.11. Seems that something has changed in Popen. Don't investigated it for now.

ThEnGI commented 1 year ago

Actually it's not possible to declare different resolutions for models.

I figured it was one resolution for all streams! which is just what I was looking for Dirty or not is perfect, I don't know why but copy and paste doesn't work, from git it works. Tested CB 720p and 480p

With a view to improvement: Isn't it possible to write it so that if the requested resolution (eg 1080p) is not available, does the function look for the best resolution? in this case you would have two functions if the result of the first is null you start the second. So you can add it to the program without impacting its original functionality.

Again abusing your kindness, is it possible to write a script that returns the available resolutions?

Thank you so much !!!

DerBunteBall commented 1 year ago

Python can be a bit wild when it's copied because of the indentation and so on.

All yes.

It would be possible e.g. to make a parameter in parameters.py which is used as option. It would be also possible that the function gets more logic. It wouldn't be needed to make multiple functions because it could behave on a convention (e.g. if configured resolution doesn't exist get the best and return the chunktlist of that and if only one exists just (no variant list) just echo).

Yes it's possible to create e.g. a tool like sm-resolution.py which could get a model with a site as options which then gives a list of available resolutions to Terminal. As a hint: The sites which are supported by yt-dlp or youtube-dl should have this feature there e.g. yt-dlp -F https://chaturbate.com/modelname/ shows something like this:

ID EXT RESOLUTION |   TBR PROTO  | VCODEC        VBR ACODEC     ABR
-- --- ---------- - ----- ------ - ----------- ----- --------- ----
0  mp4 426x240    |  488k m3u8_n | avc1.42c015  488k mp4a.40.2   0k
1  mp4 854x480    | 1258k m3u8_n | avc1.4d401f 1258k mp4a.40.2   0k
2  mp4 1280x720   | 3396k m3u8_n | avc1.4d401f 3396k mp4a.40.2   0k
3  mp4 1920x1080  | 5628k m3u8_n | avc1.640028 5628k mp4a.40.2   0k

I think @lossless1024 should decide how to implement the resolution thing.

Best Regards

ThEnGI commented 1 year ago

Thanks,DerBunteBall youtube-dl is enough. Now is working with about 30 cams: CB/CAM4/MFC/StripChat/StreaMate. 15 active in 480p So far no errors on screen, time for a WE endurance test

Have a great weekend

lossless1024 commented 1 year ago

I added it. Check it if you have issues, but I tested all sites and it seems to work properly

maddi4u commented 1 year ago

Great work.

NikitaBeloglazov commented 1 year ago

Please write about quality choice in the README. Without mentioning in the readme, this function seems to be hidden from prying eyes 👀 There is a table of qualities, but there is no how to choose quality:)