Skip to main content

GStreamer

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.

note

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
gstreamermap required
GStreamer Configuration.

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
ParameterTypeDescription
widthintframe will be resized to this width
heightintframe will be resized to this height
draw_objectsanyIf this query parameter is set to a truthy value (true, 1 etc), found objects will be drawn
draw_object_maskanyIf this query parameter is set to a truthy value (true, 1 etc), configured object masks will be drawn
draw_motionanyIf this query parameter is set to a truthy value (true, 1 etc), detected motion will be drawn
draw_motion_maskanyIf this query parameter is set to a truthy value (true, 1 etc), configured motion masks will be drawn
draw_zonesanyIf this query parameter is set to a truthy value (true, 1 etc), configured zones will be drawn
mirroranyIf this query parameter is set to a truthy value (true, 1 etc), mirror the image horizontally.
rotateanyDegrees to rotate the image. Positive/negative values rotate clockwise/counter clockwise respectively
danger

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.

note

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
/config/config.yaml
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

To enable debug logging for gstreamer, add the following to your config.yaml
/config/config.yaml
logger:
logs:
viseron.components.gstreamer: debug