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
andon_unpublish
, while the callbacks for playback areon_play
andon_stop
.
Note: Before SRS 4, there were
on_connect
andon_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.
Heartbeat
SRS will send heartbeat to the HTTP callback server. This allows you to monitor the health of SRS server. Enable this feature by:
# heartbeat to api server
# @remark, the ip report to server, is retrieve from system stat,
# which need the config item stats.network.
heartbeat {
# whether heartbeat is enabled.
# Overwrite by env SRS_HEARTBEAT_ENABLED
# default: off
enabled off;
# the interval seconds for heartbeat,
# recommend 0.3,0.6,0.9,1.2,1.5,1.8,2.1,2.4,2.7,3,...,6,9,12,....
# Overwrite by env SRS_HEARTBEAT_INTERVAL
# default: 9.9
interval 9.3;
# when startup, srs will heartbeat to this api.
# @remark: must be a restful http api url, where SRS will POST with following data:
# {
# "device_id": "my-srs-device",
# "ip": "192.168.1.100"
# }
# Overwrite by env SRS_HEARTBEAT_URL
# default: http://127.0.0.1:8085/api/v1/servers
url http://127.0.0.1:8085/api/v1/servers;
# the id of device.
# Overwrite by env SRS_HEARTBEAT_DEVICE_ID
device_id "my-srs-device";
# whether report with summaries
# if on, put /api/v1/summaries to the request data:
# {
# "summaries": summaries object.
# }
# @remark: optional config.
# Overwrite by env SRS_HEARTBEAT_SUMMARIES
# default: off
summaries off;
}
By enable the summaries
, you can get the SRS server states, such as self.pid
and self.srs_uptime
, so you
can use this to determine whether SRS restarted.
Note: About fileds of
summaries
, see HTTP API: summaries for details.
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, toallow
ordeny
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