8000 GitHub - xaionaro-go/avd: (Lib)AV Daemon: a streaming server/router based on libav
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

xaionaro-go/avd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

avd -- (Lib)AV Daemon

avd -- is a streaming server that uses libav under the hood (as an alternative to nginx-module-rtmp, mediamtx, MonaServer or whatnot).

On one hand, libav is a legendary, powerful, fine-polished and fine-tuned video/audio processing library, that supports RTMP, RTSP, SRT and other protocols out of the box. On the other hand, libav lacks capabilities to serve these protocols beyond just accepting a pre-defined stream or/and using the protocols as a client.

avd fixes that problem, by wrapping around libav to manage multiple streams, that could be processed pretty similar to how you would do it with a normal streaming server.

Motivation

The best I found as a streaming server was mediamtx, but unfortunately it handled pretty poorly all of my edge cases. While I need a tool I can trust: a tool that just works.

Investigating myself all the intricacies of H264, RTMP, RTSP, SRT, HEVC, AAC, etc, to find a way to workaround mediamtx was taking too much time. Moreover, mediamtx does not allow really integrating into other projects (because it keeps everything in internal) which is in a strong conflict with one of my hobby project.

So I decided to just reuse all the fine-polishing of libav a make a server out of that. Gladfully, I've already previously made a library that makes that easy: avpipeline.

The alternatives tried before starting this project

  • nginx-module-rtmp: very poor debugging, does not support the protocols I need; and not integratable into another Go project.
  • mediamtx: does not work on my edge cases; and not integratable into another Go project.
  • livego: it was much worse than mediamtx for my use cases (do not remember the exact reasons); and not integratable into another Go project.
  • go2rtc: it appeared to be just a forwarding/routing server, rather than a normal server (e.g.: ITS#1238); not integratable into another Go project; and even those were not problems by now I'm convinced it would not have handled my edge cases better than mediamtx.
  • So on.

I also tried to solve my problems with just small libraries/packages, e.g. github.com/yutopp/go-rtmp (see also github.com/xaionaro-go/go-rtmp), but all of them were even further from supporting my edge cases. For example, IIRC, go-rtmp did not even support multihour streams (the timestamp field in RTMP was overflowing).

The general pattern is that a project:

  • Does not support protocols I need.
  • Works badly in edge cases.
  • Is too difficult to build for Android/iOS/Linux/whatever.
  • Is not integratable into an existing Go project.
  • Has major bugs/limitations even in normal cases.

So the hope is that if I'll just use libav I'll avoid these problems better than the other projects, but with focus on solving my personal edge cases.

Quick start (daemon)

$ avd --generate-config | tee ~/.avd.conf
ports:
- address: tcp:127.0.0.1:1936
  mode: "publishers"
  publish_mode: exclusive-ta
8000
keover
  protocol_handler:
    rtmp: {}
  default_route_path: ""
  on_end: "close_consumers"
- address: tcp:0.0.0.0:1935
  mode: "consumers"
  publish_mode: exclusive-takeover
  protocol_handler:
    rtmp: {}
  default_route_path: ""
  on_end: "close_consumers"
- address: tcp:0.0.0.0:1937
  mode: "consumers"
  publish_mode: exclusive-takeover
  protocol_handler:
    rtmp: {}
  default_route_path: ""
  on_end: "wait_for_new_publisher"
- address: tcp:127.0.0.1:8555
  mode: "publishers"
  publish_mode: exclusive-takeover
  protocol_handler:
    rtsp:
      transport_protocol: ""
  default_route_path: ""
  on_end: "close_consumers"
- address: udp:127.0.0.1:4445
  mode: "publishers"
  publish_mode: exclusive-takeover
  protocol_handler:
    mpegts: {}
  default_route_path: mystream
  on_end: "close_consumers"
endpoints:
  mystream:
    forwardings:
    - destination: {}
      recoding:
        audio_track_configs:
        - input_track_ids:
          - 0
          - 1
          - 2
          - 3
          - 4
          - 5
          - 6
          - 7
          output_track_ids:
          - 0
          codec_name: copy
          averaging_period: 0s
          average_bit_rate: 0
          custom_options: []
          hardware_device_type: 0
          hardware_device_name: ""
        video_track_configs:
        - input_track_ids:
          - 0
          - 1
          - 2
          - 3
          - 4
          - 5
          - 6
          - 7
          output_track_ids:
          - 1
          codec_name: copy
          averaging_period: 0s
          average_bit_rate: 0
          custom_options: []
          hardware_device_type: 0
          hardware_device_name: ""
$ avd

It should work. Now let's do something useful:

Modify the config to:

ports:
- address: tcp:127.0.0.1:1936
  rtmp:
    mode: "publishers"
endpoints:
  mystream:
    forwardings:
    - destination:
        url: "rtmp://127.0.0.1:1399/test-stream"

Run:

$ ffplay -f flv -listen 1 rtmp://127.0.0.1:1399/test-stream

Run the avd again:

$ avd

Now send some stream to avd, e.g.:

$ ffmpeg -re -i /tmp/1.flv -c copy -f flv rtmp://127.0.0.1:1936/mystream

In result, you'll see that ffplay is playing your stream:

ffmpeg -> avd -> ffplay

Quick start (package)

An example of an RTMP server:

import (
	"fmt"
	"net"

	"github.com/xaionaro-go/avd/pkg/avd"
)

func serveRTMP(ctx context.Context) error {
	srv := avd.NewServer()

	_, err = srv.Listen(ctx, "tcp:127.0.0.1:1936", avd.ProtocolRTMP, avd.RTMPModePublishers)
	if err != nil {
		return fmt.Errorf("unable to listen %s with the RTMP-publishers handler: %w", publishersListener.Addr(), err)
	}

	_, err = srv.Listen(ctx, "tcp:0.0.0.0:1935", avd.ProtocolRTMP, avd.RTMPModeConsumers)
	if err != nil {
		return fmt.Errorf("unable to listen %s with the RTMP-consumers handler: %w", consumersListener.Addr(), err)
	}

	srv.Wait(ctx)
	return nil
}

Unfortunately we have to split publishers and consumers to two ports due to internal limitations of libav.

About

(Lib)AV Daemon: a streaming server/router based on libav

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

0