ChristianKnedel / DockerChaturbateRecorderGUI

ChaturbateRecorderInterface records any video stream from Chaturbate
18 stars 5 forks source link

Not an issue just to lazy to make a pull request. #30

Closed Dethkiller15 closed 1 month ago

Dethkiller15 commented 1 month ago

Hello again here to make a small contribution to this repo.

I have seen that docker uses a F ton of resources for the containers being launched(ya I should have figured years ago lol) As a small bonus I can now actually tell what is being recorded without having to do "docker ps" in a terminal and looking at how long its been running, as it no longer does a launch to see it is still booting up since the last check just for it to fail. which was actually very annoying.(also less writes to my Mirco SD card(using a R Pi 4 and on my 3rd Micro SD card now after 2 years of this.)) So I went and made it so that if there isn't a stream on the streamers page then it wont even launch it. You just need to do 2 things.

Add a line to requirements.txt requests==2.28.1

And do the modifications seen below in docker_adapter.py(only edited to add import lines and modify the startInstance function.)

import requests
import re

class DockerAdapter(object):
    def getInstances(self, prefix):
        return "docker container ls --format '{{.Names}}' | grep '" + prefix + "'"

    def stopInstance(self, containerName):
        return "docker exec '{}' pkill -int ffmpeg &".format(containerName)

    def startInstance(self, media_path, containerName, title, limit_in_gb, imageName, UID, GID, resolution):
        # Form the URL using the title
        url = f"https://chaturbate.com/{title}/"

        # Fetch the HTML content from the URL
        response = requests.get(url)
        html_content = response.text

        # Find all occurrences of URLs ending with .m3u8
        urls = re.findall(r'https://[a-zA-Z0-9.+-_:/]*\.m3u8', html_content)

        if urls:
            # Return the Docker command if .m3u8 URLs are found
            FoundStreamVar = "Found stream for {}.".format(
                title
            )
            # print(FoundStreamVar)
            return "docker run -d -e LIMIT_MAXIMUM_FOLDER_GB={} -e UID={} -e GID={} --rm -v {}:/code/videos/ --name {} {} /code/recorder.sh -u https://chaturbate.com/{}/ -c {} -r {} &".format(
                limit_in_gb,
                UID,
                GID,
                media_path, 
                containerName, 
                imageName,
                title,
                containerName,
                resolution
            )
        else:
            StreamNotFoundVar = "No stream found for {}.".format(
                title
            )
            # print(StreamNotFoundVar)

            return "echo No Stream found for title {}. Skipping. > /dev/null 2>&1".format(
                title
            )

Oh and since you are already getting the stream URL anyways you can pass that to the recorder instead of the stream page. No need to do the check twice. Should be freakishly easy to do as well....... I will get onto that myself :)

As I don't know to much about coding in python I had ChatGPT do most of the work. :P

Do note that the above doesn't need a rebuild of the recorder in order to implement. However if you want it to make 1 less request to the site then go right on ahead and implement the changes below.

Dethkiller15 commented 1 month ago

Oh and since you are already getting the stream URL anyways you can pass that to the recorder instead of the stream page. No need to do the check twice. Should be freakishly easy to do as well....... I will get onto that myself :)

Yaaaaaaa it was ridiculously easy. Though I haven't implemented it myself quite yet.(I did and fixed a glaring issue oops XD)

In recorder.sh just change the following lines

TIMESTAMP=$(date +%Y-%m-%d_%H-%M-%S)

[ ! -d "/code/videos/${SLUG}" ] && mkdir -p "/code/videos/${SLUG}"
chown -R recorder:recorder "/code/videos/${SLUG}"
nice -n 19 ffmpeg -loglevel error -hide_banner -nostats -i ${URL} -s ${RESULUTION}  -c:a copy -c:v copy /code/videos/${SLUG}/${SLUG}-${TIMESTAMP}.mp4

And in the docker_adapter.py that you see above. Just change

        if urls:
            # Return the Docker command if .m3u8 URLs are found
            FoundStreamVar = "Found stream for {}.".format(
                title
            )
            # print(FoundStreamVar)
            return "docker run -d -e LIMIT_MAXIMUM_FOLDER_GB={} -e UID={} -e GID={} --rm -v {}:/code/videos/ --name {} {} /code/recorder.sh -u https://chaturbate.com/{}/ -c {} -r {} &".format(
                limit_in_gb,
                UID,
                GID,
                media_path, 
                containerName, 
                imageName,
                title,
                containerName,
                resolution
            )

to this

        if urls:
            url = re.sub(r'\\u([0-9A-Fa-f]{4})', lambda m: chr(int(m.group(1), 16)), urls[0])
            # Return the Docker command if .m3u8 URLs are found
            FoundStreamVar = "Found stream for {}.".format(
                title
            )
            #print(FoundStreamVar)
            return "docker run -d -e LIMIT_MAXIMUM_FOLDER_GB={} -e UID={} -e GID={} --rm -v {}:/code/videos/ --name {} {} /code/recorder.sh -u {} -c {} -r {} &".format(
                limit_in_gb,
                UID,
                GID,
                media_path, 
                containerName, 
                imageName,
                url,
                containerName,
                resolution
            )

And it SHOULD just work.

Afternote: So the streams I was recording ended soon after I posted this and I decided to implement. Ya original changes I made didn't work so I did some digging and turns out that I was actually passing a messy array/url to the docker command. Fixed it up with once again ChatGPT and now the edits you see above are working as intended.

I skipped the rebuild and just did live testing by passing a new docker_adapter.py to the container and made edits live while it was running until I got the solution.

ChristianKnedel commented 1 month ago

Hay @Dethkiller15 , thanks for your help! I will test and merge the change tonight

Dethkiller15 commented 1 month ago

Hay @Dethkiller15 , thanks for your help! I will test and merge the change tonight

Sweet also I am fairly sure Kubernetes may have the same issue and could use roughly the same modifications.

Dethkiller15 commented 1 month ago

I think it would break the shell adapter so here is the updated code that again should just work.

import requests
import re

class ShellAdapter(object):
   def getInstances(self, prefix):
        return "ps -aux | grep 'recorder.sh' | awk '{ print $16 }' | sed -e '/^ *$/d'"

   def stopInstance(self, containerName):
        return "kill -int $(ps -aux | grep 'ffmpeg' | grep '" + containerName + "' | awk '{ print $2 }')"

   def startInstance(self, media_path, containerName, title, limit_in_gb, imageName, UID, GID, resolution):
        # Form the URL using the title
        url = f"https://chaturbate.com/{title}/"

        # Fetch the HTML content from the URL
        response = requests.get(url)
        html_content = response.text

        # Find all occurrences of URLs ending with .m3u8
        urls = re.findall(r'https://[a-zA-Z0-9.+-_:/]*\.m3u8', html_content)

        if urls:
            url = re.sub(r'\\u([0-9A-Fa-f]{4})', lambda m: chr(int(m.group(1), 16)), urls[0])
            # Return the recorder command if .m3u8 URLs are found
            FoundStreamVar = "Found stream for {}.".format(
                title
            )
            # print(FoundStreamVar)
            return "/recorder/recorder.sh -u {} -c {} -r {} &".format(
            url,
            containerName,
            resolution
            )
        else:
            StreamNotFoundVar = "No stream found for {}. Skipping.".format(
                title
            )
            # print(StreamNotFoundVar)

            return "echo No Stream found for title {}. Skipping. > /dev/null 2>&1".format(
                title
            )

I did 0 testing but I basically just modified the script I made for the docker adapter.

Dethkiller15 commented 1 month ago

oh and for performance with the docker adapter on my raspberry Pi 4(8gb). With 16 being watched went from a constant flux between 10-80% CPU utilization(without anything being recorded) to just 5-30% with 16 being watched and 4 actively being recorded.(note that I am recording to a SMB share hosted on another device so in reality it should be better for those not doing that.)

ChristianKnedel commented 1 month ago

hi @Dethkiller15 , please check the changes $ docker-compose -f dev_adapter_docker.yml build $ docker-compose -f dev_adapter_docker.yml up

Dethkiller15 commented 1 month ago

I had a look in what you did to check_chaturbate.py and I think it is kinda useless to make request for the page in that section of the code as when you go into docker_adapter.py or shell_adapter.py in interface/utils/adapter/adapter/ it has to make a request there anyways.

The changes I suggested are for docker_adapter.py and shell_adapter.py as that would leave the same amount of requests in to the site without doing anything much to the container itself.

I think the changes you had made specifically to check the page outside those 2 files are nearly useless unless you really needed to do a double check.

Dethkiller15 commented 1 month ago

I updated my fork and made the changes myself.

https://github.com/Dethkiller15/DockerChaturbateRecorderGUI/tree/master

I did 0 testing but it should be fine with what I assume to be the adapter of choice for you the shell adapter @ChristianKnedel

I am nearly 100% sure that the changes I had done to the 3.0 version work flawlessly but again I had done 0 testing with your latest updates.

ChristianKnedel commented 1 month ago

I see we understand each other! I'm going to close this ticket now