Giter Club home page Giter Club logo

rtmp_relay's Introduction

RTMP relay v1.0

Build Status Build Status

Relays RTMP streams to multiple endpoints.

Usage

RTMP relay uses yaml-cpp submodule. The following command has to be run after cloning the RTMP relay:

$ git submodule update --init

To compile the RTMP relay, just run "make" in the root directory. You can pass these arguments to rtmp_relay (located in the bin directory):

  • --config <config_file> – path to config file
  • --daemon – run RTMP relay as daemon
  • --kill-daemon – kill the daemon
  • --reload-config – reload the daemon's configuration
  • --help – print the documentation

Docker build

Check out submodules the same way as for a normal build, then run docker-compose build. This will result in a local image named evo-rtmp-relay:latest.

Configuration

RTMP relay configuration files are YAML-based. It must start with servers array. Each server has following attributes:

  • endpoints – array of endpoint descriptors
    • applicationName – for host streams this is the filter of incoming stream application names (can contain a regex), for client streams this is the name of the application (optional)
    • streamName – for host streams this is the filter of incoming stream names (can contain a regex), for client streams this is the name of the stream (optional)
    • type – type of connection (client or host)
    • direction – direction of the stream (input or output)
    • addresses – list of addresses to connect to (for client connections) or listen to (for server connections)
    • video – flag that indicates whether to forward video stream (default value is true)
    • audio – flag that indicates whether to forward audio stream (default value is true)
    • data – flag that indicates whether to forward data stream (default value is true)
    • metaDataBlacklist – list of metadata fields that should not be forwarded
    • connectionTimeout – how long should the attempt to connect last (default value is 5.0)
    • reconnectInterval – the interval of reconnection (default value is 5.0)
    • reconnectCount – amount of connect attempts (0 to reconnect forever)
    • pingInterval – client ping interval in seconds (default value is 60.0)
    • bufferSize – size of the client buffer for input streams (default value is 3000)
    • amfVersion – AMF version (for client connections) to use for communication (default value is 0)

applicationName can have the following tokens:

  • {id} – id of the application
  • {applicationName} – name of the application
  • {streamName} – name of the stream
  • {ipAddress} – IP address of the destination
  • {port} – destination port

streamName name can have the following tokens:

  • {id} – id of the sender
  • {applicationName} – name of the application
  • {streamName} – name of the source stream
  • {ipAddress} – IP address of the destination
  • {port} – destination port

Optionally you can add a web status page with "statusPage" object, which has the following attribute:

  • address – the address of the web status page

Status page can be accessed in the following addresses:

  • <server address>/stats – HTML output
  • <server address>/stats.html – HTML output
  • <server address>/stats.json – JSON output
  • <server address>/stats.txt – text output

To configure logging, you can add "log" object to the config file. It has the following attributes

  • level – the log threshold level (0 for no logs and 4 for all logs)
  • syslogEnabled – should the syslog be used (default value is true) (on *NIX only)
  • syslogIdent – identification to be passed to openlog (on *NIX only)
  • syslogFacility – facility to be passed to openlog (on *NIX only)

Example configuration:

log:
    level: 4
    syslogIdent: relay
    syslogFacility: "LOG_LOCAL3"
statusPage:
    address: "0.0.0.0:80"
servers:
  - endpoints:
      - addresses: [ "0.0.0.0:13004" ]
        type: "host"
        direction: "input"
        applicationName: "app/name"
        video: true
        audio: true
      - addresses: [ "52.19.130.93:1935" ]
        type: "client"
        direction: "output"
        applicationName: "app/name"
        streamName: "stream_name"
        video: true
        audio: true
        pingInterval: 60.0
      - addresses: [ "127.0.0.1:13005" ]
        type: "client"
        direction: "output"
        applicationName: "app/name"
        streamName: "{streamName}_2"
        video: true
        audio: true
        pingInterval: 60.0
        connectionTimeout: 5.0
        reconnectInterval: 5.0
        reconnectCount: 3

rtmp_relay's People

Contributors

elnormous avatar agriic avatar theyellowarchitect avatar

Stargazers

 avatar  avatar Gregor Vostrak avatar Yuri Nagibovich avatar Nikita Popov avatar  avatar Richie Chan avatar GAURAV avatar pickle avatar  avatar  avatar Ilya Melamed avatar IRLKit avatar Leet avatar Christian Heusel avatar  avatar Chiao F avatar CMK avatar Egor avatar Tawmu avatar Kian G. Movasagi avatar Luka Čabraja avatar Aheahead avatar Tiger Cox avatar  avatar Pavel Trostianko avatar Curllog avatar  avatar Philmist avatar Luis Sala avatar Ben Thomas avatar  avatar haozi avatar Kimmo Vuorinen avatar along avatar 仓鼠 avatar Matthew McWilliams avatar Alex avatar Gordian Zhang avatar David Wozniak avatar RoestVrijStaal avatar Carl Calcara avatar Keith Mitchell avatar  avatar RuioWolf avatar  avatar Lion avatar Andrii Davydov avatar  avatar DAVID RUPP JR. avatar Jason Duke avatar Josh Dvir avatar  avatar Aaron Benkoczy avatar  avatar JB Hewitt avatar Joseph Higgins avatar Vico avatar  avatar Patrick Connolly avatar zhangjs avatar Viesturs Proškins avatar John Manos avatar  avatar

Watchers

JB Hewitt avatar Neustradamus avatar James Cloos avatar Alex avatar  avatar Metaeditor avatar  avatar David Bowdoin avatar  avatar  avatar  avatar zhangjie avatar Stephen Bridgwater avatar  avatar  avatar

rtmp_relay's Issues

Add a license

Please add a license, this would make it easier for other people to use your software, and to contribute to the repository!

Multiple streams over a singel connection

How hard would this be to modify a bit to support multiple streams over a single connection? I've been looking for a relay like this, but haven't found one that can ingest multiple inputs from separate connections, and push them out to remote locations, but all over a single connection with each remote location. Everything I've been able to find creates a new connection for each stream.

RTMP Buffer / Delay add

Hey there,

Would love to add a new feature - the ability to add a significant delay (say 5-15mins).

OBS/Xsplit do this by saving to ram before streaming - obsproject/obs-studio@0538865

probably a very difficult thing to do but for us this is critical

Thanks!

Keeps crashing on connect (in src/Amf.hpp:210)

Unfortunately the server keeps crashing instantly when I connect via OBS (am I doing something wrong?)

This is the redacted config:

log:
    level: 4
    syslogIdent: relay
    syslogFacility: "LOG_LOCAL3"
statusPage:
    address: "0.0.0.0:13005"
servers:
  - endpoints:
      - address: [ "0.0.0.0:13004" ]
        type: "host"
        direction: "input"
        applicationName: "app/chaos"
        video: true
        audio: true
      - address: [ "live.twitch.tv:1935" ]
        type: "client"
        direction: "output"
        applicationName: "app/live_XXX?bandwidthtest=true"
        streamName: "twitch"
        reconnectCount: 0

This is the (redacted) output:

/usr/local/src/rtmp_relay/bin[master]# ./rtmp_relay --config /home/chaos/rtmp-config.cfg
2019.01.27 02:43:11: Server listening on 0.0.0.0:13005
2019.01.27 02:43:11: Server listening on 0.0.0.0:13004
2019.01.27 02:43:11: -----------------  RTMP Relay sn -----------------
2019.01.27 02:43:14: Client connected from X.X.X.98:59128 to 0.0.0.0:13004
2019.01.27 02:43:14: [CON:2 /] Create connection
2019.01.27 02:43:14: Socket received 1537 bytes from X.X.X.98:59128
2019.01.27 02:43:14: [CON:2 /] Got 1537 bytes
2019.01.27 02:43:14: [CON:2 /] Got version 3
2019.01.27 02:43:14: [CON:2 /] Sending reply version 3
2019.01.27 02:43:14: [CON:2 /] Got challenge message, time: 2392521100, version: 0.0.0.0
2019.01.27 02:43:14: [CON:2 /] Sending challange reply message
2019.01.27 02:43:14: [CON:2 /] Sending Ack message
2019.01.27 02:43:14: [CON:2 /] Remaining data 0
2019.01.27 02:43:14: Socket sent 3073 bytes to X.X.X.98:59128
2019.01.27 02:43:14: Socket received 1536 bytes from X.X.X.98:59128
2019.01.27 02:43:14: [CON:2 /] Got 1536 bytes
2019.01.27 02:43:14: [CON:2 /] Got Ack reply message, time: 0, version: 2.0.0.0
2019.01.27 02:43:14: [CON:2 /] Handshake done
2019.01.27 02:43:14: [CON:2 /] Remaining data 0
2019.01.27 02:43:14: Socket received 214 bytes from X.X.X.98:59128
2019.01.27 02:43:14: [CON:2 /] Got 214 bytes
2019.01.27 02:43:14: Header type: TWELVE_BYTE(0), channel: 2, ts: 0, data length: 4, message type: SET_CHUNK_SIZE(1), message stream ID: 0, final timestamp: 0
2019.01.27 02:43:14: [CON:2 /] Total packet size: 16
2019.01.27 02:43:14: [CON:2 /] Received SET_CHUNK_SIZE, parameter: 4096
2019.01.27 02:43:14: Header type: TWELVE_BYTE(0), channel: 3, ts: 0, data length: 186, message type: AMF0_INVOKE(20), message stream ID: 0, final timestamp: 0
2019.01.27 02:43:14: [CON:2 /] Total packet size: 198
2019.01.27 02:43:14: [CON:2 /] Received INVOKE, command: Type: String(5), value: connect
2019.01.27 02:43:14: [CON:2 /] Transaction ID: Type: Double(3), value: 1.000000
2019.01.27 02:43:14: [CON:2 /] Argument 1: Type: Object(6), values:
  app: Type: String(5), value: app/chaos
  flashVer: Type: String(5), value: FMLE/3.0 (compatible; FMSc/1.0)
  swfUrl: Type: String(5), value: rtmp://xxx.xx:13004/app/chaos
  tcUrl: Type: String(5), value: rtmp://xxx.xx:13004/app/chaos
  type: Type: String(5), value: nonprivate
2019.01.27 02:43:14: Header type: TWELVE_BYTE(0), channel: 2, ts: 0, data length: 4, message type: SERVER_BANDWIDTH(5), message stream ID: 0, final timestamp: 0
2019.01.27 02:43:14: [CON:2 /] Sending SERVER_BANDWIDTH
2019.01.27 02:43:14: Header type: EIGHT_BYTE(1), channel: 2, ts: 0, data length: 5, message type: CLIENT_BANDWIDTH(6), final timestamp: 0
2019.01.27 02:43:14: [CON:2 /] Sending CLIENT_BANDWIDTH
2019.01.27 02:43:14: Header type: EIGHT_BYTE(1), channel: 2, ts: 0, data length: 6, message type: USER_CONTROL(4), final timestamp: 0
2019.01.27 02:43:14: [CON:2 /] Sending USER_CONTROL of type: CLEAR_STREAM, parameter 1: 0
2019.01.27 02:43:14: Header type: TWELVE_BYTE(0), channel: 3, ts: 0, data length: 4, message type: SET_CHUNK_SIZE(1), message stream ID: 0, final timestamp: 0
2019.01.27 02:43:14: [CON:2 /] Sending SET_CHUNK_SIZE
2019.01.27 02:43:14: Header type: EIGHT_BYTE(1), channel: 3, ts: 0, data length: 191, message type: AMF0_INVOKE(20), final timestamp: 0
2019.01.27 02:43:14: Header type: ONE_BYTE(3), channel: 3, final timestamp: 0
2019.01.27 02:43:14: [CON:2 /] Sending INVOKE _result
2019.01.27 02:43:14: Header type: EIGHT_BYTE(1), channel: 3, ts: 0, data length: 30, message type: AMF0_INVOKE(20), final timestamp: 0
2019.01.27 02:43:14: [CON:2 /] Sending INVOKE onBWDone, transaction ID: 1
2019.01.27 02:43:14: [CON:2 app/chaos/] Input from X.X.X.98:59128 sent connect, application: "app/chaos"
2019.01.27 02:43:14: [CON:2 app/chaos/] Remaining data 0
2019.01.27 02:43:14: Socket sent 297 bytes to X.X.X.98:59128
2019.01.27 02:43:14: Socket received 37 bytes from X.X.X.98:59128
2019.01.27 02:43:14: [CON:2 app/chaos/] Got 37 bytes
2019.01.27 02:43:14: Header type: EIGHT_BYTE(1), channel: 3, ts: 0, data length: 29, message type: AMF0_INVOKE(20), final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Total packet size: 37
2019.01.27 02:43:14: [CON:2 app/chaos/] Received INVOKE, command: Type: String(5), value: releaseStream
2019.01.27 02:43:14: [CON:2 app/chaos/] Transaction ID: Type: Double(3), value: 2.000000
2019.01.27 02:43:14: [CON:2 app/chaos/] Argument 1: Type: Null(1)
2019.01.27 02:43:14: Header type: EIGHT_BYTE(1), channel: 3, ts: 0, data length: 20, message type: AMF0_INVOKE(20), final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Sending INVOKE _result
2019.01.27 02:43:14: [CON:2 app/chaos/] Remaining data 0
2019.01.27 02:43:14: Socket sent 28 bytes to X.X.X.98:59128
2019.01.27 02:43:14: Socket received 92 bytes from X.X.X.98:59128
2019.01.27 02:43:14: [CON:2 app/chaos/] Got 92 bytes
2019.01.27 02:43:14: Header type: EIGHT_BYTE(1), channel: 3, ts: 0, data length: 25, message type: AMF0_INVOKE(20), final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Total packet size: 33
2019.01.27 02:43:14: [CON:2 app/chaos/] Received INVOKE, command: Type: String(5), value: FCPublish
2019.01.27 02:43:14: [CON:2 app/chaos/] Transaction ID: Type: Double(3), value: 3.000000
2019.01.27 02:43:14: [CON:2 app/chaos/] Argument 1: Type: Null(1)
2019.01.27 02:43:14: Header type: EIGHT_BYTE(1), channel: 3, ts: 0, data length: 14, message type: AMF0_INVOKE(20), final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Sending INVOKE onFCPublish
2019.01.27 02:43:14: Header type: ONE_BYTE(3), channel: 3, final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Total packet size: 26
2019.01.27 02:43:14: [CON:2 app/chaos/] Received INVOKE, command: Type: String(5), value: createStream
2019.01.27 02:43:14: [CON:2 app/chaos/] Transaction ID: Type: Double(3), value: 4.000000
2019.01.27 02:43:14: [CON:2 app/chaos/] Argument 1: Type: Null(1)
2019.01.27 02:43:14: Header type: EIGHT_BYTE(1), channel: 3, ts: 0, data length: 29, message type: AMF0_INVOKE(20), final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Sending INVOKE _result
2019.01.27 02:43:14: Header type: TWELVE_BYTE(0), channel: 3, ts: 0, data length: 21, message type: AMF0_INVOKE(20), message stream ID: 0, final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Total packet size: 33
2019.01.27 02:43:14: [CON:2 app/chaos/] Received INVOKE, command: Type: String(5), value: _checkbw
2019.01.27 02:43:14: [CON:2 app/chaos/] Transaction ID: Type: Double(3), value: 5.000000
2019.01.27 02:43:14: [CON:2 app/chaos/] Argument 1: Type: Null(1)
2019.01.27 02:43:14: Header type: EIGHT_BYTE(1), channel: 3, ts: 0, data length: 20, message type: AMF0_INVOKE(20), final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Sending INVOKE _result
2019.01.27 02:43:14: [CON:2 app/chaos/] Remaining data 0
2019.01.27 02:43:14: Socket sent 87 bytes to X.X.X.98:59128
2019.01.27 02:43:14: Socket received 42 bytes from X.X.X.98:59128
2019.01.27 02:43:14: [CON:2 app/chaos/] Got 42 bytes
2019.01.27 02:43:14: Header type: TWELVE_BYTE(0), channel: 4, ts: 0, data length: 30, message type: AMF0_INVOKE(20), message stream ID: 1, final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Total packet size: 42
2019.01.27 02:43:14: [CON:2 app/chaos/] Received INVOKE, command: Type: String(5), value: publish
2019.01.27 02:43:14: [CON:2 app/chaos/] Transaction ID: Type: Double(3), value: 6.000000
2019.01.27 02:43:14: [CON:2 app/chaos/] Argument 1: Type: Null(1)
2019.01.27 02:43:14: [CON:2 app/chaos/] Argument 2: Type: String(5), value:
2019.01.27 02:43:14: Application "app/chaos", stream "" matched endpoint application "app/chaos", stream ""
2019.01.27 02:43:14: Address 0.0.0.0:13004 matched address 0.0.0.0:13004
2019.01.27 02:43:14: Application: "app/chaos", stream: "" did not match endpoint application: "app/live_XXX?bandwidthtest=true", stream: "twitch"
2019.01.27 02:43:14: Header type: ONE_BYTE(3), channel: 2, final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Sending USER_CONTROL of type: CLEAR_STREAM, parameter 1: 0
2019.01.27 02:43:14: Header type: EIGHT_BYTE(1), channel: 3, ts: 0, data length: 141, message type: AMF0_INVOKE(20), final timestamp: 0
2019.01.27 02:43:14: Header type: ONE_BYTE(3), channel: 3, final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Sending INVOKE onStatus
2019.01.27 02:43:14: [ST:3 app/chaos/] Create
2019.01.27 02:43:14: [CON:2 app/chaos/] Input from X.X.X.98:59128 published stream ""
2019.01.27 02:43:14: [ST:3 app/chaos/] Stream start [CON:2 app/chaos/]
2019.01.27 02:43:14: [CON:4 app/live_XXX?bandwidthtest=true/twitch] Create connection
2019.01.27 02:43:14: Connecting to 185.42.205.245:1935
2019.01.27 02:43:14: [CON:2 app/chaos/] Remaining data 0
2019.01.27 02:43:14: Socket sent 157 bytes to X.X.X.98:59128
2019.01.27 02:43:14: Socket connected to 185.42.205.245:1935
2019.01.27 02:43:14: [CON:4 app/live_XXX?bandwidthtest=true/twitch] Connected to 185.42.205.245:1935
2019.01.27 02:43:14: [CON:4 app/live_XXX?bandwidthtest=true/twitch] Sending version message 3
2019.01.27 02:43:14: [CON:4 app/live_XXX?bandwidthtest=true/twitch] Sending challenge message
2019.01.27 02:43:14: Socket sent 1537 bytes to 185.42.205.245:1935
2019.01.27 02:43:14: Socket received 411 bytes from X.X.X.98:59128
2019.01.27 02:43:14: [CON:2 app/chaos/] Got 411 bytes
2019.01.27 02:43:14: Header type: TWELVE_BYTE(0), channel: 4, ts: 0, data length: 399, message type: AMF0_DATA(18), message stream ID: 1, final timestamp: 0
2019.01.27 02:43:14: [CON:2 app/chaos/] Total packet size: 411
2019.01.27 02:43:14: [CON:2 app/chaos/] Received NOTIFY, command: Type: String(5), value: @setDataFrame
2019.01.27 02:43:14: [CON:2 app/chaos/] Argument 1: Type: String(5), value: onMetaData
2019.01.27 02:43:14: [CON:2 app/chaos/] Argument 2: Type: Dictionary(8), values:
  2.1: Type: Boolean(4), value: false
  3.1: Type: Boolean(4), value: false
  4.0: Type: Boolean(4), value: false
  4.1: Type: Boolean(4), value: false
  5.1: Type: Boolean(4), value: false
  7.1: Type: Boolean(4), value: false
  audiochannels: Type: Double(3), value: 2.000000
  audiocodecid: Type: String(5), value: mp4a
  audiodatarate: Type: Double(3), value: 160.000000
  audiosamplerate: Type: Double(3), value: 44100.000000
  audiosamplesize: Type: Double(3), value: 16.000000
  duration: Type: Double(3), value: 0.000000
  encoder: Type: String(5), value: obs-output module (libobs version 22.0.3)
  fileSize: Type: Double(3), value: 0.000000
  framerate: Type: Double(3), value: 60.000000
  height: Type: Double(3), value: 800.000000
  stereo: Type: Boolean(4), value: true
  videocodecid: Type: String(5), value: avc1
  videodatarate: Type: Double(3), value: 2500.000000
  width: Type: Double(3), value: 1280.000000
rtmp_relay: src/Amf.hpp:210: uint32_t relay::amf::Node::asUInt32() const: Assertion `type == Type::Integer || type == Type::Double' failed.
Aborted

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.