thelabcat / rumble-chat-actor

Interact with the chat of your livestreams in Python
GNU General Public License v3.0
2 stars 0 forks source link

Clip command could possibly be more efficient by grabbing local video stream #6

Closed thelabcat closed 3 months ago

thelabcat commented 4 months ago

A developer for RumBot pointed out to me that downloading clips from Rumble is rather round Robin's barn if the clip system is running on the streaming computer. Why not just grab the local video output straight from OBS? I've looked into this, and found a few possible options for how to send video from OBS to Python via plugins+libraries:

  1. NDI: The Python library would not install properly. When Pip called cmake, the script could not find the cmake module. Cmake called by user in command line works normally. Suspect a problem with Pip. Unsure where to report.
  2. Spout 2: The OBS plugin side says it is Windows only. I insist on cross-platform.
  3. SRT: OBS can stream out to this internally, but the Multi-RMTP plugin would be required to actually output to Rumble. This could work. The OpenCV library appears capable of reading SRT streams.
  4. Virtual camera: Does not include audio, and syncing audio output with a latent video stream seems too complicated to implement.

I'm kinda burned out on making the existing implementation work, but I do intend to implement this in the future.

thelabcat commented 3 months ago

Renamed current clip command, since it will still be useful for third-party actor running.

thelabcat commented 3 months ago

Did not mean to close, oops.

thelabcat commented 3 months ago

Good news! Test code successfully received and saved a VOB stream via TCP from OBS. We used the Advanced output settings to have FFmpeg send the "recording" from OBS to a local host. TYJ!

import socket
import select
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 3119))
s.listen(1)
if True:
    c, info = s.accept()
    print("connected")
    f = open("test.vob", "wb")
    data = True
    while data:
        select.select([c], [], [])
        data = c.recv(1024)
        print("data received")
        f.write(data)
    f.close()

image

thelabcat commented 3 months ago

Better method: Record to an ordinary TS file, and do this:

import os
import shutil
from tkinter import filedialog, Tk
from moviepy.editor import VideoFileClip

root = Tk()
root.withdraw()
fn = filedialog.askopenfilename(title = "Select OBS recording in progress")
container = fn.split(".")[-1]
copy_fn = "recording_isolated." + container

input("Press enter to save clip")

print("Making frozen copy of recording")
shutil.copy(fn, copy_fn)
print("Loading copy")
recording = VideoFileClip(copy_fn)
print("Trimming")
clip = recording.subclip(max((recording.duration - 10, 0)), recording.duration)
print("Saving clip")
clip.write_videofile("test.mp4", logger = None)
print("Closing and deleting frozen copy")
recording.close()
os.system("rm " + copy_fn)

Basically, the TS file will still have FFmpeg-compatible duration information even if copied mid-recording. I did a test, and there's about a 2 second delay before the live goes to file, which considering stream latency is probably fine. TYJ, we have a stage two!