Seite 1 von 1

mal eben ein UI ... blutiger anfäger rennt vor eine Wand

Verfasst: Freitag 16. Juli 2021, 09:46
von S3R43o3
Nun zu erst ich bin blutiger Anfänger sowohl in Sachen programmieren als auch in Sachen Python.
Nun habe ich mit einen Screen recorder gebaut der auch funktioniert nur gefällt mir die CMD nicht und wollte daher ein nettes GUI haben. Dachte kann ja nich so schwer sein 2 Buttons 1 text vielleicht ein Hilfe Button.
Joah hab ich wohl die Rechnung nich mit python gemacht.
Ich spreche schon gut englisch jedoch sind fachspezifische texte unglaublich schwer zu verstehen wenn nicht in der Muttersprache geschrieben.
Gestartet habe ich hiermit:
das funktioniert auch alles wie es soll.

Code: Alles auswählen

import cv2, numpy, pyautogui, keyboard
import PySimpleGUI as UI



filename = 'Bildschirmaufnahme' 
SCREEN_SIZE = (1920, 1080)
vid = cv2.VideoWriter(filename + ".mp4", cv2.VideoWriter_fourcc(*'mp4v'),20.0,(SCREEN_SIZE))
print("Starte Aufnahme.\nDrücke 'X' auf deiner Tastatur um die Aufnahme zu beenden...")
while True:
    img = pyautogui.screenshot()
    numpy_frame = numpy.array(img)
    frame = cv2.cvtColor(numpy_frame, cv2.COLOR_BGR2RGB)
    vid.write(frame)
    if keyboard.is_pressed('x'):
        print("Stoppe Aufnahme.")
        break
cv2.destroyAllWindows()
vid.release()
und hier nun der Klägliche Versuch den Code umzubauen *ich schäm mcih schon ein wenig ...

Code: Alles auswählen

import tkinter as tk 
import cv2, numpy, pyautogui, keyboard, time




# --------------- Funktionen ------------------
def start():
    global running

    if running is not None:
        print('Ich laufe bereits')
    else:
        frame = cv2.cvtColor(numpy_frame, cv2.COLOR_BGR2RGB)
        running = vid.write(frame)
        running.start_recording()

def stop():
    global running

    if running is not None:
        running.stop_recording()
        vid.release()
        cv2.destroyAllWindows()
        running = None
    else:
        print('Ich laufe nicht mehr')


# ---------------------- Main ------------------------------
filename = "Bildschirmaufnahme"
SCREEN_SIZE = (1920, 1080)
vid = cv2.VideoWriter(filename + ".mp4", cv2.VideoWriter_fourcc(*'mp4v'), 20.0,(SCREEN_SIZE))
img = pyautogui.screenshot()
numpy_frame = numpy.array(img)
running = None

root = tk.Tk()

button_rec = tk.Button(root, text="Start", command=start)
button_rec.pack()

button_stop = tk.Button(root, text="Stop", command=stop)
button_stop.pack()

root.mainloop()

Der selbstverständlich nich das tut was er soll.. Ich bekomme zwar die Ausgabe einer mp4. Datei aber es ist wohl so das er nur solang aufnimmt solange der button im gedrückt zustand ist...
Ich forsche nun schon seit 2 Tagen im Netz habe Mir Qt, Tkinter, SimpleGUI angeschaut aber iwie komme ich nich zu einer Lösung. Ich glaube nicht das ich dafür threadding brauche oder ?
Ich bin über jegliche Hilfe unglaublich dankbar und vielen Dank im allgemeinen für eurer geteiltest Knowhow und eure Zeit!
Liebe Grüße

Bitte seid gnädig

Re: mal eben ein UI ... blutiger anfäger rennt vor eine Wand

Verfasst: Freitag 16. Juli 2021, 10:32
von __blackjack__
@S3R43o3: Doch dafür brauchst Du Threads wenn die Aufnahme mit Code entstehen soll, der neben der GUI laufen muss. Und damit ist das definitiv nichts mehr als erstes Anfängerprojekt, denn sowohl Threads als auch GUIs sind für sich genommen schon komplex. Alternativ kannst Du schauen welchen Mechanismus das verwendete GUI-Rahmenwerk bietet um nach einer bestimmten Zeitspanne eine Funktion/Methode aufzurufen, in der dann eine einzelne Aufnahme gemacht und kodiert werden kann. Bei `tkinter` wäre das die `after()`-Methode auf Widgets.

Für GUIs braucht man objektorientierte Programmierung (OOP), und dafür die Grundlage wäre es das man auch saubere Programme mit Funktionen schreiben kann. Das ist beiden Programmen von Dir nicht ersichtlich. ``global`` vergisst Du beispielsweise am besten sofort wieder. Funktionen (und Methoden) bekommen alles was sie ausser Konstanten benötigen, als Argument(e) übergeben, und Ergebnisse werden an den Aufrufer mit ``return`` zurückgegeben. Und um Zustand über Aufrufe hinweg zu speichern, braucht man dann OOP, also eigene Klassen.

Mehrere GUI-Rahmenwerke sollte man in der Regel nicht mischen. Den `VideoWriter` von OpenCV kannst Du verwenden, aber Du solltest keine GUI oder Benutzerinteraktion aus dem Paket zusammen mit einem GUI-Rahmenwerk benutzen. Das kann funktionieren, muss es aber nicht.

Re: mal eben ein UI ... blutiger anfäger rennt vor eine Wand

Verfasst: Freitag 16. Juli 2021, 10:49
von __blackjack__
@S3R43o3: Anmerkungen zum ersten Quelltext:

Importe von mehreren Modulen werden üblicherweise nicht zu einer ``import``-Anweisung zusammengefasst. Siehe Style Guide for Python Code.

`PySimpleGUI` wird importiert, aber nicht verwendet.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

`filename` ist eine Konstante und sollte deshalb KOMPLETT_GROSS geschrieben werden.

Die Klammern bei der Verwendung von `SCREEN_SIZE` sind überflüssig.

Namen sollte man nicht kryptisch Abkürzungen. Und man muss auch nicht jedes Zwischenergebnis an einen eigenen Namen binden.

Den `release()`-Aufruf sollte man mit einem ``try``/``finally`` auch sicherstellen wenn die Aufnahme durch eine Ausnahme beendet wird.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import cv2
import keyboard
import numpy
from pyautogui import screenshot

BASE_FILENAME = "Bildschirmaufnahme"
SCREEN_SIZE = (1920, 1080)  # TODO Dynamisch ermitteln.


def main():
    video_writer = cv2.VideoWriter(
        BASE_FILENAME + ".mp4",
        cv2.VideoWriter_fourcc(*"mp4v"),
        20,
        SCREEN_SIZE,
    )
    try:
        print(
            "Starte Aufnahme.\n"
            "Drücke 'X' auf deiner Tastatur um die Aufnahme zu beenden..."
        )
        while True:
            video_writer.write(
                cv2.cvtColor(numpy.array(screenshot()), cv2.COLOR_BGR2RGB)
            )
            if keyboard.is_pressed("x"):
                print("Stoppe Aufnahme.")
                break

        cv2.destroyAllWindows()
    finally:
        video_writer.release()


if __name__ == "__main__":
    main()

Re: mal eben ein UI ... blutiger anfäger rennt vor eine Wand

Verfasst: Freitag 16. Juli 2021, 14:30
von S3R43o3
Okay dann ersteinmal vielen Dank ich dachte mir Schon das die Problematik dahin führt... Nun ich bin mit JS vertraut dort kann ich einfach ein process laufen lassen.
Herzlichen dank nocheinmal dann lege ich das mal auf Seite =D
Was die sache mit dem import angeht das war nur ein vergessenes rest stück beim Copy/paste

Re: mal eben ein UI ... blutiger anfäger rennt vor eine Wand

Verfasst: Freitag 16. Juli 2021, 14:32
von S3R43o3
was anderes ... das script einfach so aufrufen über ein anderes funktioniert da nicht ? per import oder so ?

Re: mal eben ein UI ... blutiger anfäger rennt vor eine Wand

Verfasst: Freitag 16. Juli 2021, 16:10
von S3R43o3
nun nach Etwas tüffeln habe ich ein Workaround gefunden.
Leider habe ich dein Snippet nicht zum laufen bekommen.
Aber der hier tut in etwa das was ich wollte.
Die automatische größe funktioniert auch =)

Code: Alles auswählen

import cv2
import numpy
import keyboard
import pyautogui as ui

SCREEN_SIZE = width, height = ui.size()
info2 = "\n\bNach dem drücken des 'Ok'-Buttons wird die Aufnahme automatisch gestartet."
info1 = "Bitte schreibe den Titel deiner Aufnahme in die Eingabe unten."
wichtig1 = "\n\bUm die Aufnahme zu beenden drücke 'X' auf deiner Tastatur."


filename = ui.prompt(text=info1 + info2 + wichtig1, title="Name der Aufnahme", default="")    
vid = cv2.VideoWriter(filename + ".mp4", cv2.VideoWriter_fourcc(*'mp4v'), 30.0, (SCREEN_SIZE))

while True:
    img = ui.screenshot()
    numpy_frame = numpy.array(img)
    frame = cv2.cvtColor(numpy_frame, cv2.COLOR_BGR2RGB)
    vid.write(frame)
    if keyboard.is_pressed('x'):
        print("Stoppe Aufnahme.")
        ui.alert("Deine Aufnahme wurde erstellt.", 'Achtung!', button='OK')
        break
cv2.destroyAllWindows()
vid.release()

Re: mal eben ein UI ... blutiger anfäger rennt vor eine Wand

Verfasst: Freitag 16. Juli 2021, 20:44
von __blackjack__
@S3R43o3: Mein ”Snippet” ist vollständig und ich habe es gerade ausprobiert — das läuft bei mir. Nervigerweise nur als Admin, weil das `keyboard`-Modul diese Rechte braucht. Aber das wäre bei Deinem letzten Quelltext ja auch der Fall.

Dein Programm kommt nicht damit klar wenn der Benutzer den Dialog mit der Frage nach dem Dateinamen per Button oder Fenster schliessen abbricht.