Webcam Livestream

  • Hallo!

    Ich habe vor kurzem einen Snippet gelesen, um Audio-Daten (vom Mic), über TCP an einen anderen Rechner zu streamen.

    Das gleiche möchte ich jetzt mit .avi-Dateien von einer Webcam machen - allerdings nicht über die VLC-Api (die läuft nämlich nicht so super), nicht über Einzelbilder und nicht über einen Browser.

    Allerdings finde ich den Snippet nicht mehr, und ich weiß nicht, wie ich "halbe" Videos zum laufen kriegen soll.

  • Obwohl ich nicht mit Einzelnbildern arbeiten wollte, habe ich die Übertragung mit JPEG jetzt hinbekommen.

    Wens mal interessiert:

    Server

    Spoiler anzeigen
    [autoit]

    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_outfile=Server.exe
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

    [/autoit] [autoit][/autoit] [autoit]

    #include <WindowsConstants.au3>
    #include <WebcamConstants.au3>
    #include <GUIConstants.au3>
    #include <GDIPlus.au3>

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup()

    [/autoit] [autoit][/autoit] [autoit]

    TCPStartup()
    $listen = TCPListen(@IPAddress1, 1234)
    Do
    $tcp = TCPAccept($listen)
    Until $tcp <> -1

    [/autoit] [autoit][/autoit] [autoit]

    $gui = GUICreate("Webcam", 160, 120)

    [/autoit] [autoit][/autoit] [autoit]

    $dll_avi = DllOpen("avicap32.dll")
    $dll_user = DllOpen("user32.dll")

    [/autoit] [autoit][/autoit] [autoit]

    $cap = DllCall($dll_avi, "int", "capCreateCaptureWindow", "str", "cap", "int", BitOR($WS_CHILD, $WS_VISIBLE), "int", 0, "int", 0, "int", 160, "int", 120, "hwnd", $gui, "int", 1)

    [/autoit] [autoit][/autoit] [autoit]

    DllCall($dll_user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_DRIVER_CONNECT, "int", 0, "int", 0)
    DllCall($dll_user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_SET_SCALE, "int", 1, "int", 0)
    DllCall($dll_user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_SET_OVERLAY, "int", 1, "int", 0)
    DllCall($dll_user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_SET_PREVIEW, "int", 1, "int", 0)
    DllCall($dll_user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_SET_PREVIEWRATE, "int", 1, "int", 0)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState(@SW_SHOW)

    [/autoit] [autoit][/autoit] [autoit]

    $timer = TimerInit()
    $fps = 10
    While 1
    If (GUIGetMsg() = $GUI_EVENT_CLOSE) Then
    ExitLoop
    EndIf
    If (TimerDiff($timer) > 1000 / $fps) Then
    $timer = TimerInit()
    DllCall($dll_user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_GRAB_FRAME_NOSTOP, "int", 0, "int", 0)
    DllCall($dll_user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_FILE_SAVEDIBA, "int", 0, "str", "temp.bmp")
    $img = _GDIPlus_ImageLoadFromFile("temp.bmp")
    _GDIPlus_ImageSaveToFile($img, "temp.jpg")
    _GDIPlus_ImageDispose($img)
    TCPSend($tcp, StringToBinary(FileRead("temp.jpg")))
    EndIf
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    DllCall($dll_user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_END, "int", 0, "int", 0)
    DllCall($dll_user, "int", "SendMessage", "hWnd", $cap[0], "int", $WM_CAP_DRIVER_DISCONNECT, "int", 0, "int", 0)
    DllClose($dll_user)

    [/autoit]

    Client-Programm

    Spoiler anzeigen
    [autoit]

    #include <GUIConstants.au3>
    GUICreate("Test", 320, 240)
    $pic = GUICtrlCreatePic("", 0, 0, 320, 240)
    GUISetState(@SW_SHOW)
    TCPStartup()
    $tcp = TCPConnect(@IPAddress1, 1234)
    While 1
    If (GUIGetMsg() = $GUI_EVENT_CLOSE) Then
    ExitLoop
    EndIf
    $r = TCPRecv($tcp, 1024)
    FileWrite("tcp.jpg", Binary($r))
    If (BinaryMid($r, BinaryLen($r)-1, 2) = "0xFFD9") Then
    GUICtrlSetImage($pic, "tcp.jpg")
    FileDelete("tcp.jpg")
    EndIf
    WEnd

    [/autoit]
  • Ist dein Problem jetzt eigentlich gelöst?
    Wenn ja, setze doch bitte das Präfix im ersten Post auf "gelöst", ansonsten formuliere bitte deine Frage.
    PS: Du kannst Beiträge auch editieren, Doppel- / Dreifachposts und Pushen sind verpönt.

  • Ich glaube nicht, dass es gelöst ist.
    Er sucht doch nach einem Livestream.

    Eine Idee zu dem ganzen:
    2 Sekunden Video aufnehmen (in einen Buffer) versenden.
    Der Client sollte dann die Videos empfangen und ebenfalls einen 2 Sekunden Buffer verwenden.
    Bedeutet im Grunde genommen, dass immer ein 2 Sekunden Video geguckt und direkt danach gelöscht wird und so weiter..

  • Zitat

    2 Sekunden Video aufnehmen (in einen Buffer) versenden.

    geht nur dann, wenn du reichlich Bandbreite zur Verfügung hast, um auch mal lost frames (wären dann 2 Sekunden^^) aufzufangen bzw auszugleichen.
    Wenn man vom einfachsten Videostream ~ 3 MBit mit MPEG2 ausgeht, wird es auf einer 10MBit-Leitung schon eng. Datenmüll empfangen, Paket nochmal anfordern und nochmal gesendet bekommen frisst bei nur einem einzigen Fehler sofort den gesamten Puffer von 2 Sekunden auf!
    Video-Streamen würde ich daher mit einem dafür ausgelegten Programm, den Datenstrom in kleine Bröckchen zu packen und "zu Fuss" per AutoIt zu verschicken halte ich für suboptimal.

    Im DeskStream haben Sprenger120 und ich uns am streamen eines Desktops versucht, für "normale" Fensteranwendungen gibts da keinerlei Probleme mit der Geschwindigkeit im Fullscreen, aber bei Video (große aufeinanderfolgende, stark unterschiedliche Bilddaten) wirds kritisch. Und zwar haben wir dort nur die Differenzen zum vorhergehenden Frame gepackt, komprimiert und versendet. Frame für Frame....

    Im 100MBit-internen Netz werden auch Videos bei erträglichen Frameraten mit Grössen von 500x400 Pixel übertragen, ohne Ton natürlich.
    Im 10MBit-Netz (etwa Internetgeschwindigkeit) sind bei Videogrössen ab 300x200 Pixeln noch 25FPS machbar, bei doppelt so grossen Videos sinkt entsprechend die Framerate
    Aber das halte ich für die Gegebenheiten, 350 Zeilen Code für Client und Server, schon völlig in Ordnung! Aber kein Vergleich zu einer professionellen Videostreaming-Software, welche natürlich auch mit völlig anderm Hintergrund arbeitet. Stream <> Stream^^