SRT publishing from many authors¶
To accept SRT publishing from multiple authors while centrally issuing a unique passphrase to each author, use the srt_port_resolve
mechanism offered by Flussonic for SRT publishing to the cloud. For more information about this solution, see SRT page.
Note
An alternative is to add streams to the Flussonic configuration manually. But this method doesn’t work well when you have dozens of servers and thousands of authors: you will need to somehow determine which server to receive a stream from this or that author, and the passphrase will be stored in configuration files that are not automatically synchronized on the servers.
Step 1. Develop a configuration backend¶
Each author publishes their content to a pre-allocated port with own passphrase. A configuration backend manages the stream configuration to match ports to stream names and stream names to passphrases. Below is a simple example of such a configuration backend.
from http.server import BaseHTTPRequestHandler, HTTPServer
import urllib.parse as urlparse
class RequestHandler(BaseHTTPRequestHandler):
streams_config = {
"streams": [
{
"name": "publish_stream_name",
"inputs": [
{"url": "publish://"}
],
"srt_publish": {"passphrase": "securePass"}
},
{
"name": "other_publish_stream",
"inputs": [
{"url": "publish://"}
],
"srt_publish": {"passphrase": "otherPassword"}
}
]
}
port_stream_mapping = (
(2345, "publish_stream_name"),
(2346, "other_publish_stream"),
)
def do_GET(self):
parsed_path = urlparse.urlparse(self.path)
path = parsed_path.path
query_components = urlparse.parse_qs(parsed_path.query)
# Handle /config_backend/streams
if path.startswith('/config_backend/streams'):
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
response = self.streams_config
self.wfile.write(bytes(str(response), "utf8"))
# Handle /config_backend/srt_port_resolve/{port}
elif path.startswith('/config_backend/srt_port_resolve/'):
port = int(path.split('/')[-1])
mode = query_components.get('mode', [None])[0]
host = query_components.get('host', [None])[0]
response = next((stream_name for port_number, stream_name in self.port_stream_mapping if port_number == port), None)
if response and mode == 'publish':
self.send_response(200)
self.send_header('Content-Type', 'text/plain')
self.end_headers()
self.wfile.write(bytes(response, "utf8"))
else:
self.send_error(400, "Invalid port or mode.")
return
else:
self.send_error(404, "404 Not Found")
def run(server_class=HTTPServer, handler_class=RequestHandler, port=12345):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print(f'Starting httpd on port {port}...')
httpd.serve_forever()
if __name__ == "__main__":
from sys import argv
if len(argv) == 2:
run(port=int(argv[1]))
else:
run()
To run this configuration backend:
- Save the above code to the file
/tmp/config_server.py
using any text editor. -
Install Python if not already installed.
apt install python3
-
Launch the configuration backend on a free port, for example, 12345.
python3 /tmp/server.py 12345
Step 2. Configure Flussonic to use the configuration backend¶
You have to tell Flussonic where to fetch streams and which ports to listen for SRT publications. Send the configuration backend address and the SRT port range via PUT /streamer/api/v3/config API call:
curl -u USER:PASSWORD -X PUT http://localhost:80/streamer/api/v3/config \
-H "Content-Type: application/json" \
--data '{"listeners": {"srt": [ {"mode":"publish","ports":{"first":2345,"last":12344}}]},"config_external": "http://localhost:12345/config_backend/"}'
The publish_stream_name
and other_publish_stream
streams retrieved by Flussonic from the configuration backend should be created in the UI within 5-10 seconds after executing this command.
Step 3. Test the setup¶
Publish the stream to Flussonic:
ffmpeg -re -i /opt/flussonic/priv/bunny.mp4 -c copy -y -f mpegts 'srt://localhost:2345?passphrase=securePass'
Check that the video is playing in the publish_stream_name
stream profile on the Overview tab in the UI.