GStreamer
The GStreamer integration reads frames from your cameras for processing by Viseron.
Viseron uses the gst-launch-1.0
command to interface with GStreamer.
Hardware acceleration is available and automatically used for the NVIDIA Jetson Nano
.
As of now the gstreamer
integration uses FFmpeg to create recordings when an object is detected and FFprobe to read stream information.
Therefore, if you make changes to the recorder
config you should keep in mind that it is in FFmpeg syntax.
Configuration
Configuration example
gstreamer:
camera:
camera_one:
name: Camera 1
host: 192.168.XX.XX
port: 554
path: /Streaming/Channels/101/
username: !secret camera_one_user
password: !secret camera_one_pass
mjpeg_streams:
my_stream:
width: 100
height: 100
draw_objects: true
rotate: 45
mirror: true
recorder:
idle_timeout: 5
camera_two:
name: Camera 2
host: 192.168.YY.YY
port: 554
path: /Streaming/Channels/101/
username: !secret camera_two_user
password: !secret camera_two_pass
Camera
A camera domain fetches frames from a camera source and distributes it to other domains in Viseron.
MJPEG Streams
Viseron will serve MJPEG streams of all cameras.
Dynamic streams
The dynamic streams are automatically created for each camera. They utilize query parameters to control what is displayed on the stream.
Example URL: http://localhost:8888/<camera_identifier>/mjpeg-stream
Query parameters
A number of query parameters are available to instruct Viseron to resize the stream or draw different things on the image.
To utilize a parameter you append it to the URL after a ?
. To add multiple parameters you separate them with &
, like this:
http://localhost:8888/<camera name slug>/mjpeg-stream?<parameter1>=<value>&<parameter2>=<value>`
Expand to see all available query parameters
Parameter | Type | Description |
---|---|---|
width | int | frame will be resized to this width |
height | int | frame will be resized to this height |
draw_objects | any | If this query parameter is set to a truthy value (true , 1 etc), found objects will be drawn |
draw_object_mask | any | If this query parameter is set to a truthy value (true , 1 etc), configured object masks will be drawn |
draw_motion | any | If this query parameter is set to a truthy value (true , 1 etc), detected motion will be drawn |
draw_motion_mask | any | If this query parameter is set to a truthy value (true , 1 etc), configured motion masks will be drawn |
draw_zones | any | If this query parameter is set to a truthy value (true , 1 etc), configured zones will be drawn |
mirror | any | If this query parameter is set to a truthy value (true , 1 etc), mirror the image horizontally. |
rotate | any | Degrees to rotate the image. Positive/negative values rotate clockwise/counter clockwise respectively |
If you are going to have more than one consumer of the stream, it is better to configure your own static MJPEG streams. This is because each dynamic stream will process their frames individually, duplicating the processing.
Static streams
The MJPEG streams work exactly as the dynamic streams, but instead of defining the query parameters in the URL, they are defined in the config.yaml
The benefit of using these predefined streams instead is that frame processing happens only once.
This means that you can theoretically have as many streams open as you want without increased load on your machine.
Config example
<component that provides camera domain>:
camera:
front_door:
...
mjpeg_streams:
my-big-front-door-stream:
width: 100
height: 100
draw_objects: true
my-small-front-door-stream:
width: 100
height: 100
draw_objects: true
draw_zones: true
draw_object_mask: true
The config example above would give you two streams, available at these endpoints:
http://localhost:8888/front_door/mjpeg-streams/my-big-front-door-stream
http://localhost:8888/front_door/mjpeg-streams/my-small-front-door-stream
GStreamer pipeline
Viseron will try to generate a suitable decoder pipeline.
As of now only the Jetson Nano
has a special pipeline which utilizes hardware acceleration.
If you have experience working with GStreamer, please suggest other pipelines in a PR or an issue!
GStreamer audio pipeline
If your camera has audio, an audio pipeline will be automatically added to the GStreamer command.
The pipeline is rather crude and always re-encodes the audio to aac
.
This is not optimal, but it works. Hopefully this will be improved in the future.
The default audio pipeline looks like this in YAML format:
audio_pipeline:
- "input_stream."
- "!"
- "queue"
- "!"
- "decodebin"
- "!"
- "audioconvert"
- "!"
- "queue"
- "!"
- "voaacenc"
- "!"
- "mux.audio_0"
FFprobe Stream Information
Viseron needs to know the width, height, FPS and audio/video codecs of your stream.
FFprobe is used on initialization to figure all this information out.
Some cameras dont play nice with this and fail to report some information.
To circumvent this you can manually specify all these options.
If you specify all of width
, height
, fps
, codec
and audio_codec
, Viseron will not need to call FFprobe and startup will be significantly faster.
Recoverable Errors
GStreamer occasionally prints error messages which are of no real significance.
To suppress an error you can add a subset of that error to the gstreamer_recoverable_errors
config option.
gstreamer_recoverable_errors:
- error while decoding MB
Rotating video
If you rotate your camera 90 or 180 degrees, you can rotate the video in Viseron to match.
To do this you can use the output_element
and video_filters
option in the config.
If you are rotating the video 90 degrees, you need to tell Viseron the width and height of the video, which should be the opposite of the cameras real resolution.
If you have a camera with 1920x1080 resolution, you need to set width: 1080
and height: 1920
in the config.
Config to rotate 90 degrees clockwise
gstreamer:
camera:
camera_one:
name: Camera 1
host: 192.168.XX.X
port: 554
path: /Streaming/Channels/101/
username: !secret camera_one_user
password: !secret camera_one_pass
output_element: "videoflip method=clockwise !" # Rotate the frames processed by Viseron
width: 1080 # Width of the rotated video = height of the camera
height: 1920 # Height of the rotated video = width of the camera
recorder:
idle_timeout: 5
video_filters: # Rotate the recorded videos, handled by FFmpeg as of now.
- transpose=1
Raw pipeline
If you want to use a custom GStreamer pipeline, you can do so by specifying the raw_pipeline
option.
Viseron needs to be able to read frames, so you must make sure to output frames to stdout.
By default this is done using the fdsink
element, but other elements might work as well.
You also need to make sure that you are outputting frames in the raw format (video/x-raw
) that Viseron expects.
The third consideration is that small segments need to be saved to disk for processing by the recorder.
This is done by using the splitmuxsink
element.
Last but not least, if you create a pipeline that works well for your particular hardware, please consider contributing it to Viseron, either by opening a PR or an issue.
Troubleshooting
gstreamer
, add the following to your config.yaml
logger:
logs:
viseron.components.gstreamer: debug