abhiTronix / vidgear

A High-performance cross-platform Video Processing Python framework powerpacked with unique trailblazing features :fire:
https://abhitronix.github.io/vidgear
Apache License 2.0
3.37k stars 254 forks source link

Support for rtmp broadcast #48

Closed locdoan12121997 closed 4 years ago

locdoan12121997 commented 5 years ago

Is there any way I can implement rtmp broadcast using your api, NetGear for example.

Question

Acknowledgment

Context

I already have a rtmp server running and a vlc rtmp subscriber. Now, I need an rtmp publisher using your library or opencv.

Your Environment

Optional

The solution I expect should be like this

from vidgear.gears import VideoGear
from vidgear.gears import NetGear

stream = VideoGear(source=0).start() 
options = {flag : 0, copy : False, track : False}
server = NetGear(address = '127.0.0.1', port = '1935', protocol = 'rtmp',  pattern = 0, receive_mode = False, logging = True, **options) 

while True:
    try: 
        frame = stream.read()
        if frame is None:
            break
        server.send(frame)

    except KeyboardInterrupt:
        break

stream.stop()
server.close()
abhiTronix commented 5 years ago

Now, I need an rtmp publisher using your library or opencv.

@locdoan12121997 You don't need a separate API for doing this but you can simply use VidGear's powerful CamGear API for this purpose. Just feed the URL of the device/app you want to stream to the source parameter of CamGear API to implement an RTMP publisher as follows:

from vidgear.gears import CamGear
import cv2

stream = CamGear(source='rtmp://127.0.0.1:1935').start() # feed your correct rtmp URL here

# infinite loop
while True:

    frame = stream.read()
    # read frames

    # check if frame is None
    if frame is None:
        #if True break the infinite loop
        break

    # do something with frame here

    cv2.imshow("Output Frame", frame)
    # Show output window

    key = cv2.waitKey(1) & 0xFF
    # check for 'q' key-press
    if key == ord("q"):
        #if 'q' key-pressed break out
        break

cv2.destroyAllWindows()
# close output window

stream.stop()
# safely close video stream.
abhiTronix commented 5 years ago

Closed. Feel free to reopen if it doesn't work for you.

TerehinAV commented 4 years ago

Good day! I continue to try to create a stream with the processed video. Question: can I use vidgear with ffserver? In this case, an audio track is not needed.

The case is:

  1. The url of the stream is transmitted to the input.
  2. The script processes the frames.
  3. frames are transmitted to ffserver

In the console without processing, this could be done by a command like:

ffmpeg -i <source_url> -vcodec libx264 -tune zerolatency -crf 18 http://localhost:1234/feed1.ffm

Where http://localhost:1234/feed1.ffm - from ffserver config

The final goal is to create processed video stream (rtmp) with URL, which can be opened in any player that supports this (for example, VLC)

abhiTronix commented 4 years ago

@TerehinAV

can I use vidgear with ffserver?

Nope, only the FFmpeg pipeline is accessible with vidgear.

In the console without processing, this could be done by a command like:

ffmpeg -i -vcodec libx264 -tune zerolatency -crf 18 http://localhost:1234/feed1.ffm

If you want to implement this command then follow following steps as before:

git clone https://github.com/abhiTronix/vidgear.git
cd vidgear
git checkout development
sudo pip3 install .
cd

type your url here

source_url = "www/forexample.com/r.mp4" output_url = "http://localhost:1234/feed1.ffm"

open stream

stream = VideoGear(source=source_url).start() #Open input video stream for getting framerate

ready your parameters

output_params = {"-input_framerate":stream.framerate} #assign framerate

close stream

stream.stop()

define writer

writer = WriteGear(output_filename = 'Output.mp4', logging = True, **output_params) #Define writer

define parameter

ffmpeg_command = ['-y', '-i', source_url, '-vcodec', 'libx264', '-tune', 'zerolatency', '-crf', '18', output_url]

-y parameter is to overwrite outputfile if exists

execute FFmpeg command

writer.execute_ffmpeg_cmd(ffmpeg_command)

clean resources

writer.close()

TerehinAV commented 4 years ago

This is not exactly what I'm looking for. I know how to implement original command, but I don't know how to add cv2 processing in it. In common example cv2 processing is in "while True" loop, and execute_ffmpeg_cmd is calling after writer's close method is called. And I'm looking for a way to process frames and stream it "on the go" like NetGear's send method.

abhiTronix commented 4 years ago

I know how to implement original command, but I don't know how to add cv2 processing in it. In common example cv2 processing is in "while True" loop, and execute_ffmpeg_cmd is calling after writer's close method is called. And I'm looking for a way to process frames and stream it "on the go" like NetGear's send method.

@TerehinAV To implement this, You need an live RTSP pipeline over FFmpeg. This can be the next enhancement to vidgear but currently, I don't have enough time to make this implementation. I'll add this feature in the next release. For now, kindly use NetGear API for network streaming with vidgear and also for live WebRTC streaming with opencv see this library: https://github.com/aiortc/aiortc

TerehinAV commented 4 years ago

Thanks! I'll try what you advised and look forward to the new release of Vidgear

abhiTronix commented 4 years ago

@TerehinAV See http://trac.ffmpeg.org/wiki/ffserver. The support for FFserver has been removed, with a warning stating that:

Warning: ffserver has been removed on 2018-01-06. If you still need it checkout commit 2ca65fc or use the 3.4 release branch. The original documentation has been archived and can be downloaded as ​HTML or ​PDF while the sample ffserver configuration file can be found below. We can provide no support for ffserver.

Therefore I don't think we can work on this feature anymore.

abhiTronix commented 4 years ago

WriteGear API now supports URLs as input. Successfully resolved and merged in commit d76c8be.

JacobBothell commented 4 years ago

I have followed your example that is in the code and tried to replicate what your function test is doing but i am still not able to stream to a local rtmp server the line i am erroring on is:

writer = WriteGear(output_filename = 'rtmp://localhost/relay/test", logging = True)

i am getting the error:

AssertionError: [WriteGear:ERROR] :: Permission Denied: Cannot write to directory: [...]/rtmp:/localhost/relay

My system is Ubuntu 18.04 Python 3.6.9

abhiTronix commented 4 years ago

AssertionError: [WriteGear:ERROR] :: Permission Denied: Cannot write to directory: [...]/rtmp:/localhost/relay

@JacobBothell This feature hasn't been merged into master branch yet. Install vidgear with testing branch using these instructions: https://abhitronix.github.io/vidgear/installation/source_install/#installation for trying it out early.

RTY0310 commented 4 years ago

WriteGear :: WARNING :: The given path:rtmp://192.6.94.12/live/test does not have write access permission. Skipped! WriteGear :: DEBUG :: Compression Mode is enabled therefore checking for valid FFmpeg executables. WriteGear :: DEBUG :: Output_params Dict: {'-vcodec': 'h264_nvmpi'} Helper :: DEBUG :: Final FFmpeg Path: ffmpeg Helper :: DEBUG :: FFmpeg validity Test Passed! Helper :: DEBUG :: Found valid FFmpeg Version: b'd359b75' installed on this system WriteGear :: DEBUG :: Found valid FFmpeg executables: ffmpeg. Helper :: DEBUG :: URL scheme rtmp is supported by FFmpeg. WriteGear :: DEBUG :: URL:rtmp://192.6.94.12/live/test is sucessfully configured for streaming. WriteGear :: DEBUG :: Compression Mode is configured properly! WriteGear :: DEBUG :: InputFrame => Height:720 Width:1280 Channels:1 WriteGear :: DEBUG :: Executing FFmpeg command: ffmpeg -y -f rawvideo -vcodec rawvideo -s 1280x720 -pix_fmt gray -i - -vcodec h264_nvmpi rtmp://192.6.94.12/live/test ffmpeg version d359b75 Copyright (c) 2000-2020 the FFmpeg developers built with gcc 7 (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) configuration: --enable-nvmpi libavutil 56. 31.100 / 56. 31.100 libavcodec 58. 54.100 / 58. 54.100 libavformat 58. 29.100 / 58. 29.100 libavdevice 58. 8.100 / 58. 8.100 libavfilter 7. 57.100 / 7. 57.100 libswscale 5. 5.100 / 5. 5.100 libswresample 3. 5.100 / 3. 5.100 Input #0, rawvideo, from 'pipe:': Duration: N/A, start: 0.000000, bitrate: 184320 kb/s Stream #0:0: Video: rawvideo (Y800 / 0x30303859), gray, 1280x720, 184320 kb/s, 25 tbr, 25 tbn, 25 tbc [NULL @ 0x558ad71ad0] Unable to find a suitable output format for 'rtmp://192.6.94.12/live/test' rtmp://192.6.94.12/live/test: Invalid argument WriteGear :: ERROR :: BrokenPipeError caught, Wrong values passed to FFmpeg Pipe, Kindly Refer Docs! Traceback (most recent call last): File "/home/keti/.local/lib/python3.6/site-packages/vidgear/gears/writegear.py", line 311, in write self.__process.stdin.write(frame.tostring()) BrokenPipeError: [Errno 32] Broken pipe

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "testvv.py", line 26, in writer.write(gray) File "/home/keti/.local/lib/python3.6/site-packages/vidgear/gears/writegear.py", line 317, in write raise ValueError # for testing purpose only ValueError

When I reinstall and run it, it does not work with the above error.

abhiTronix commented 4 years ago

[NULL @ 0x558ad71ad0] Unable to find a suitable output format for 'rtmp://192.6.94.12/live/test' rtmp://192.6.94.12/live/test: Invalid argument

@nagneff You are not defining format for your RTMP stream. See FFmpeg StreamingGuide you atleast need -preset ultrafast -vcodec libx264 -tune zerolatency -b 900k -f mpegts like parameter (remember -f format is critical) at minimum for a valid RTMP stream.