Skip to main content
Version: 6.0 (Unstable) 🚧

HTTPCallback

SRS supports HTTP callback to extends SRS. The workflow is:

+--------+     +--------+                    +-----------------------+
| FFmpeg |-->--+  SRS   |--HTTP-Callback-->--+  Your Business Server |
+--------+     +--------+                    +-----------------------+

When FFmpeg/OBS publish or play a stream to SRS, SRS will call your business server to notify the event.

Usage

First, run SRS with HTTP callback enabled:

./objs/srs -c conf/http.hooks.callback.conf

Start the demo HTTP callback server, which is your business server:

go run research/api-server/server.go

Publish a stream to SRS, with the params:

ffmpeg -re -i doc/source.flv -c copy -f flv rtmp://localhost/live/livestream?k=v

Your business server will got the HTTP event:

Got action=on_publish, client_id=3y1tcaw2, ip=127.0.0.1, vhost=__defaultVhost__, stream=livestream, param=?k=v

Note that the k=v can be used for authentication, for token authentication based on HTTP callbacks, read Token Authentication

Compile

SRS always enable http callbacks.

For more information, read Build

Configuring SRS

An example conf/http.hooks.callback.conf is available, demonstrating the configuration of common callback events for direct use.

The config for HTTP hooks is:

vhost your_vhost {
    http_hooks {
        # whether the http hooks enable.
        # default off.
        enabled         on;
        # when client(encoder) publish to vhost/app/stream, call the hook,
        # the request in the POST data string is a object encode by json:
        #       {
        #           "action": "on_publish",
        #           "client_id": "9308h583",
        #           "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
        #           "stream": "livestream", "param":"?token=xxx&salt=yyy", "server_id": "vid-werty",
        #           "stream_url": "video.test.com/live/livestream", "stream_id": "vid-124q9y3"
        #       }
        # if valid, the hook must return HTTP code 200(Status OK) and response
        # an int value specifies the error code(0 corresponding to success):
        #       0
        # support multiple api hooks, format:
        #       on_publish http://xxx/api0 http://xxx/api1 http://xxx/apiN
        # @remark For SRS4, the HTTPS url is supported, for example:
        #       on_publish https://xxx/api0 https://xxx/api1 https://xxx/apiN
        on_publish      http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams;
        # when client(encoder) stop publish to vhost/app/stream, call the hook,
        # the request in the POST data string is a object encode by json:
        #       {
        #           "action": "on_unpublish",
        #           "client_id": "9308h583",
        #           "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
        #           "stream": "livestream", "param":"?token=xxx&salt=yyy", "server_id": "vid-werty",
        #           "stream_url": "video.test.com/live/livestream", "stream_id": "vid-124q9y3"
        #       }
        # if valid, the hook must return HTTP code 200(Status OK) and response
        # an int value specifies the error code(0 corresponding to success):
        #       0
        # support multiple api hooks, format:
        #       on_unpublish http://xxx/api0 http://xxx/api1 http://xxx/apiN
        # @remark For SRS4, the HTTPS url is supported, for example:
        #       on_unpublish https://xxx/api0 https://xxx/api1 https://xxx/apiN
        on_unpublish    http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams;
        # when client start to play vhost/app/stream, call the hook,
        # the request in the POST data string is a object encode by json:
        #       {
        #           "action": "on_play",
        #           "client_id": "9308h583",
        #           "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
        #           "stream": "livestream", "param":"?token=xxx&salt=yyy",
        #           "pageUrl": "http://www.test.com/live.html", "server_id": "vid-werty",
        #           "stream_url": "video.test.com/live/livestream", "stream_id": "vid-124q9y3"
        #       }
        # if valid, the hook must return HTTP code 200(Status OK) and response
        # an int value specifies the error code(0 corresponding to success):
        #       0
        # support multiple api hooks, format:
        #       on_play http://xxx/api0 http://xxx/api1 http://xxx/apiN
        # @remark For SRS4, the HTTPS url is supported, for example:
        #       on_play https://xxx/api0 https://xxx/api1 https://xxx/apiN
        on_play         http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions;
        # when client stop to play vhost/app/stream, call the hook,
        # the request in the POST data string is a object encode by json:
        #       {
        #           "action": "on_stop",
        #           "client_id": "9308h583",
        #           "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
        #           "stream": "livestream", "param":"?token=xxx&salt=yyy", "server_id": "vid-werty",
        #           "stream_url": "video.test.com/live/livestream", "stream_id": "vid-124q9y3"
        #       }
        # if valid, the hook must return HTTP code 200(Status OK) and response
        # an int value specifies the error code(0 corresponding to success):
        #       0
        # support multiple api hooks, format:
        #       on_stop http://xxx/api0 http://xxx/api1 http://xxx/apiN
        # @remark For SRS4, the HTTPS url is supported, for example:
        #       on_stop https://xxx/api0 https://xxx/api1 https://xxx/apiN
        on_stop         http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions;
        # when srs reap a dvr file, call the hook,
        # the request in the POST data string is a object encode by json:
        #       {
        #           "action": "on_dvr",
        #           "client_id": "9308h583",
        #           "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
        #           "stream": "livestream", "param":"?token=xxx&salt=yyy",
        #           "cwd": "/usr/local/srs",
        #           "file": "./objs/nginx/html/live/livestream.1420254068776.flv", "server_id": "vid-werty",
        #           "stream_url": "video.test.com/live/livestream", "stream_id": "vid-124q9y3"
        #       }
        # if valid, the hook must return HTTP code 200(Status OK) and response
        # an int value specifies the error code(0 corresponding to success):
        #       0
        on_dvr          http://127.0.0.1:8085/api/v1/dvrs http://localhost:8085/api/v1/dvrs;
        # when srs reap a ts file of hls, call the hook,
        # the request in the POST data string is a object encode by json:
        #       {
        #           "action": "on_hls",
        #           "client_id": "9308h583",
        #           "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
        #           "stream": "livestream", "param":"?token=xxx&salt=yyy",
        #           "duration": 9.36, // in seconds
        #           "cwd": "/usr/local/srs",
        #           "file": "./objs/nginx/html/live/livestream/2015-04-23/01/476584165.ts",
        #           "url": "live/livestream/2015-04-23/01/476584165.ts",
        #           "m3u8": "./objs/nginx/html/live/livestream/live.m3u8",
        #           "m3u8_url": "live/livestream/live.m3u8",
        #           "seq_no": 100, "server_id": "vid-werty",
        #           "stream_url": "video.test.com/live/livestream", "stream_id": "vid-124q9y3"
        #       }
        # if valid, the hook must return HTTP code 200(Status OK) and response
        # an int value specifies the error code(0 corresponding to success):
        #       0
        on_hls          http://127.0.0.1:8085/api/v1/hls http://localhost:8085/api/v1/hls;
        # when srs reap a ts file of hls, call this hook,
        # used to push file to cdn network, by get the ts file from cdn network.
        # so we use HTTP GET and use the variable following:
        #       [server_id], replace with the server_id
        #       [app], replace with the app.
        #       [stream], replace with the stream.
        #       [param], replace with the param.
        #       [ts_url], replace with the ts url.
        # ignore any return data of server.
        # @remark random select a url to report, not report all.
        on_hls_notify   http://127.0.0.1:8085/api/v1/hls/[server_id]/[app]/[stream]/[ts_url][param];
    }
}

Description about some fields:

  • stream_url: The stream identify without extension, such as /live/livestream.
  • stream_id: The id of stream, by which you can query the stream information.

Note: The callbacks for streaming are on_publish and on_unpublish, while the callbacks for playback are on_play and on_stop.

Note: Before SRS 4, there were on_connect and on_close, which are events defined by RTMP and only applicable to RTMP streams. These events overlap with streaming and playback events, so their use is not recommended.

Note: You can refer to the hooks.callback.vhost.com example in the conf/full.conf configuration file.

Protocol

The detail protocol, for example, on_publish:

POST /api/v1/streams HTTP/1.1
Content-Type: application-json

Body:
{
  "server_id": "vid-0xk989d",
  "action": "on_publish",
  "client_id": "341w361a",
  "ip": "127.0.0.1",
  "vhost": "__defaultVhost__",
  "app": "live",
  "tcUrl": "rtmp://127.0.0.1:1935/live?vhost=__defaultVhost__",
  "stream": "livestream",
  "param": "",
  "stream_url": "video.test.com/live/livestream",
  "stream_id": "vid-124q9y3"
}

Note: You can use wireshark or tcpdump to verify it.

Go Example

Write Go code to handle SRS callback, for example, handling on_publish:

http.HandleFunc("/api/v1/streams", func(w http.ResponseWriter, r *http.Request) {
    b, err := ioutil.ReadAll(r.Body)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }

    fmt.Println(string(b))

    res, err := json.Marshal(struct {
        Code int `json:"code"`
        Message string `json:"msg"`
    }{
        0, "OK",
    })
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
    w.Write(res)
})

_ = http.ListenAndServe(":8085", nil)

Nodejs Koa Example

Write Nodejs/Koa code to handle SRS callback, for example, handling on_publish:

const Router = require('koa-router');
const router = new Router();

router.all('/api/v1/streams', async (ctx) => {
  console.log(ctx.request.body);

  ctx.body = {code: 0, msg: 'OK'};
});

PHP Example

Write PHP code to handle SRS callback, for example, handling on_publish:

$body = json_decode(file_get_contents('php://input'));
printf($body);

echo json_encode(array("code"=>0, "msg"=>"OK"));

HTTP Callback Events

SRS can call HTTP callbacks for events:

  • on_publish: When a client publishes a stream, for example, using flash or FMLE to publish a stream to the server.
  • on_unpublish: When a client stops publishing a stream.
  • on_play: When a client starts playing a stream.
  • on_stop: When a client stops playback.
  • on_dvr: When reap a DVR file.
  • on_hls: When reap a HLS file.

For events on_publish和on_play:

  • Return Code: SRS requires that the response is an int indicating the error, 0 is success.

Notes:

  • Event: When this event occurs, call back to the specified HTTP URL.
  • HTTP URL: Can be multiple URLs, split by spaces, SRS will notify all one by one.
  • Data: SRS will POST the data to specified HTTP API.

SRS will disconnect the connection when the response is not 0, or HTTP status is not 200.

SRS HTTP Callback Server

SRS provides a default HTTP callback server, using golang native http framework.

To start it:

cd research/api-server && go run server.go 8085
#2023/01/18 22:57:40.835254 server.go:572: api server listen at port:8085, static_dir:/Users/panda/srs/trunk/static-dir
#2023/01/18 22:57:40.835600 server.go:836: start listen on::8085

Remark: For SRS4, the HTTP/HTTPS url is supported, see #1657.

HTTPS Callback

HTTPS Callback is supported by SRS4, only change the callback URL from http:// to https://, for example:

vhost your_vhost {
    http_hooks {
        enabled         on;
        on_publish      https://127.0.0.1:8085/api/v1/streams;
        on_unpublish    https://127.0.0.1:8085/api/v1/streams;
        on_play         https://127.0.0.1:8085/api/v1/sessions;
        on_stop         https://127.0.0.1:8085/api/v1/sessions;
        on_dvr          https://127.0.0.1:8085/api/v1/dvrs;
        on_hls          https://127.0.0.1:8085/api/v1/hls;
        on_hls_notify   https://127.0.0.1:8085/api/v1/hls/[app]/[stream]/[ts_url][param];
    }
}

Response

If success, you must response something to identify the success, or SRS will reject the client, which enable you to reject the illegal client, please read Callback Error Code.

Note: The on_publish callback also could be used as advanced security, to allow or deny a client by its IP, or token in request url, or any other information of client.

Where something means:

  • HTTP/200, which is HTTP success.
  • AND response and int value 0, or JSON object with field code 0.

Like this:

HTTP/1.1 200 OK
Content-Length: 1
0

OR:

HTTP/1.1 200 OK
Content-Length: 11
{"code": 0}

You could run the example HTTP callback server by:

cd srs/trunk/research/api-server && go run server.go 8085

And you will finger out what's the right response.

Snapshot

The HttpCallback can used to snapshot, please read snapshot

Winlin 2015.1