Python in OBS

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
ElFiniberto
User
Beiträge: 4
Registriert: Sonntag 7. Januar 2024, 19:12

]Ich habe letztens mit jemanden telefoniert, und seine Maus hat nach 5 Sekunden Inaktivität, oder nachdem er zum zweiten bildschirm gewechselt ist so gemacht wie eine fernseher bildschirmschoner, ist also von einer seite zur anderen gebounced. er hat mir auch den code geschickt und gesagt ich müsse es in Python mit OBS machen. Ich habe es auch installier bekommen, allerdings funktioniert der code immer noch nicht. Ich habe auch die Wall szene und Cangr Quelle, welche meinen ersten bildschirm aufnimmt. pyautogui habe ich mit pip auch schon installier. Anbei sende ich den Code, danke im voraus für die Hilfe:)

Code: Alles auswählen

import obspython as S
import time
import random
import pyautogui

dvdX = 144
dvdY = 128
x_speed = 3
y_speed = 3
lastX = 0
lastY = 0
lastMove = time.time()

isCursor = False

def update_text():
    global dvdX, dvdY, x_speed, y_speed, isCursor, lastX, lastY, lastMove
    scene = S.obs_get_scene_by_name("Wall")
    scene_item = S.obs_scene_find_source(scene, "cangr")
    if scene_item:
        pos = S.vec2()
        try:
            x, y = pyautogui.position()
        except:
            x = 0
            y = 0
        if (x != lastX or y != lastY) and x > 32 and y > 32:
            lastX = x
            lastY = y
            lastMove = time.time()
        #print("Xs: " + str(x_speed) + ", Ys: " + str(y_speed) + ", x " + str(x) + " y " + str(y) + ", lastX " + str(lastX) + " lastY " + str(lastY))

        if x > 1921 or (time.time() - lastMove) > 3:
            if isCursor:
                dvdX = min(lastX, 1920 - 32)
                dvdY = min(lastY, 1080 - 32)
                x_speed = 3
                y_speed = 3
            if (dvdX >= (1920 - 32)) or (dvdX < 32):
                x_speed = -x_speed
            if (dvdY >= (1080 - 32)) or (dvdY < 32):
                y_speed = -y_speed
            dvdX += x_speed
            dvdY += y_speed
            pos.x = dvdX - 32
            pos.y = dvdY - 32
            #print("new x: " + str(dvdX) + " new y: " + str(dvdY))

            isCursor = False
        else:
            pos.x = x - 32
            pos.y = y - 32
            isCursor = True
        S.obs_sceneitem_set_pos(scene_item, pos)
    S.obs_scene_release(scene)

def start():
    S.timer_add(update_text, 17)
    S.timer_remove(start)

def script_description():
    return "cangr"

def script_load(settings):
    S.timer_add(start, 3000)

def script_unload():
    S.timer_remove(update_text)
Benutzeravatar
noisefloor
User
Beiträge: 3857
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

der Code an sich macht aus nichts, wenn man ihn ausführt - auf oberster Ebene sind nur ein paar Variablen definiert und das war's. Da kann nichts passieren.

Wie bzw. wo führst du das aus?

Gruß, noisefloor
ElFiniberto
User
Beiträge: 4
Registriert: Sonntag 7. Januar 2024, 19:12

Danke für die Antwort:), ich starte das Programm durch den "Scripte" bereich in OBS mit Python 3.6.8 und soweit ich weiß wird sobald das script geladen wird die definition script_load(settings): ausgeführt, was ja nach 3 sekunden die definition update_text alle 17 sekunden laufen lässt. Ich habe halt noch nie zuvor mit OBS Python gearbeitet, also korrigier mich wenn ich falsch liege;)

Gruß, ElFiniberto
Benutzeravatar
noisefloor
User
Beiträge: 3857
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

na ja, um dein Problem nachzustellen müsste man ja OBS installiert haben. Ich glaube aber, dass hier im Forum nicht so viele aktive Streamer unterwegs sind... Hast du deine Frage mal in einem OBS Forum gestellt?

Gruß, noisefloor
ElFiniberto
User
Beiträge: 4
Registriert: Sonntag 7. Januar 2024, 19:12

stimmt, daran habe ich gar nicht gedacht, ich persönlich streame auch nicht, aber ich habe sonst keine methode gefunden um das python script so auszuführen. Trotzdem danke für die hilfe:

Gruß, Simon
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was für ein Problem soll das denn lösen? Ist mit immer noch unklar.
Benutzeravatar
noisefloor
User
Beiträge: 3857
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
ich persönlich streame auch nicht,
Musst du ja nicht - aber für irgendwas nutzt du doch OBS, oder? Ansonsten würde die Frage nach dem Skript ja keinen Sinn machen.

Gruß, noisefloor
Benutzeravatar
__blackjack__
User
Beiträge: 13118
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ElFiniberto: Anmerkungen zum Quelltext: `random` wird importiert, aber nirgends verwendet.

In `script_unload()` sollte man auch den Timer für `start` entfernen, denn wenn man Timer entfernen muss, dann ja auch wenn das innerhalb der Zeit aufgerufen wird, die gewartet wird bis `start()` das erste mal aufgerufen wird.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Namen sollten keine kryptischen Abkürzungen enthalten. Was soll `dvd` bedeuten?

`time.time()` ist hier nicht wirklich geeignet, da sollte `time.monotonic()` verwendet werden.

Warum heisst `update_text()` so wie es heisst? Wo wird denn dort Text aktualisiert‽

``global`` hat in sauberen Programmen nichts zu suchen. Das die OBS-API keine Methoden für Rückrufe erlaubt ist äusserst hässlich.

Man kann da fast die Hälfte der globalen Variablen einsparen wenn man X und X nicht getrennt speichert, sondern sich eine Klasse dafür schreibt.

Wenn `scene` zuverlässig wieder freigegeben werden soll, sollte man das mit einem ``finally`` absichern.

Die Zeichenkette "cangr" wird zweimal verwendet. Sollte die beide male das gleiche Bedeuten, dann sollte man das als Konstante definieren.

Man verwendet kein nacktes ``except:`` ohne konkrete Ausnahmen. Das behandelt *alle* Ausnahmen, auch welche mit denen man gar nicht rechnet, verschluckt also hier auch alle möglichen Fehler, die man so nicht finden kann.

Das zusammenstückeln von Zeichenketten und Werten mittels ``+`` und `str()` ist eher BASIC als Python. Dafür gibt es die `format()`-Methode auf Zeichenketten und f-Zeichenkettenliterale.

Ungetestet:

Code: Alles auswählen

import time

import obspython as S
import pyautogui

WIDTH, HEIGHT = 1920, 1080
MARGIN = 32


class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"{self.__class__.__name__}({self.x!r}, {self.y!r})"

    def __eq__(self, other):
        return self.as_tuple() == other.as_tuple()

    def __neq__(self, other):
        return not self == other

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        return Point(self.x - other.x, self.y - other.y)

    def min(self, other):
        return Point(min(self.x, other.x), min(self.y, other.y))

    def as_tuple(self):
        return (self.x, self.y)

    def as_vec2(self):
        result = S.vec2()
        result.x, result.y = self.as_tuple()
        return result


SPEED = Point(3, 3)

dvd_position = Point(144, 128)
speed = SPEED
last_position = Point()
last_move_timestamp = time.monotonic()
is_cursor = False


def update_position():
    global dvd_position, speed, is_cursor, last_position, last_move_timestamp

    scene = S.obs_get_scene_by_name("Wall")
    try:
        scene_item = S.obs_scene_find_source(scene, "cangr")
        if scene_item:
            position = Point(*pyautogui.position())

            if (
                position != last_position
                and position.x > MARGIN
                and position.y > MARGIN
            ):
                last_position = position
                last_move_timestamp = time.monotonic()

            # print(f"{speed=}, {position=}, {last_position=}")

            if (
                position.x >= WIDTH
                or time.monotonic() - last_move_timestamp > 3
            ):
                if is_cursor:
                    dvd_position = last_position.min(
                        Point(WIDTH - MARGIN, HEIGHT - MARGIN)
                    )
                    speed = SPEED

                if not MARGIN <= dvd_position.x < WIDTH - MARGIN:
                    speed.x = -speed.x

                if not MARGIN <= dvd_position.y < HEIGHT - MARGIN:
                    speed.y = -speed.y

                dvd_position += speed
                position = dvd_position
                # print("new position:", position)
                is_cursor = False

            else:
                is_cursor = True

            S.obs_sceneitem_set_pos(
                scene_item, (position - Point(MARGIN, MARGIN)).as_vec2()
            )

    finally:
        S.obs_scene_release(scene)


def start():
    S.timer_add(update_position, 17)
    S.timer_remove(start)


def script_description():
    return "cangr"


def script_load(_settings):
    S.timer_add(start, 3000)


def script_unload():
    S.timer_remove(start)
    S.timer_remove(update_position)
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
DeaD_EyE
User
Beiträge: 1021
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Um den Code mit OBS ausführen zu können, habe ich folgendes gemacht:
  • Python-Script in Datei kopiert
  • In mein venv pyautogui installiert
  • Script angepasst:

    Code: Alles auswählen

    # header
    import sys
    
    sys.path.append("/home/deadeye/.pyenv/versions/3.12.1/lib/python3.12/site-packages")
    
    # restlicher Code unverändert
    
  • OBS gestartet
  • Script hinzufügen
  • Szene "Wall" hinzufügen
  • Irgendeine Quelle namens "cangr" hinzufügen.
Ergebnis sieht dann so aus: https://file.io/NGrScBOiYYB9

PS: Der Code ist hässlich, scheint aber zu funktionieren.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten