diff --git a/www/config.html b/www/config.html
index 7a712a3b..345bddd3 100644
--- a/www/config.html
+++ b/www/config.html
@@ -4,11 +4,17 @@
config - go2rtc
-
@@ -22,44 +28,413 @@
+
diff --git a/www/schema.json b/www/schema.json
new file mode 100644
index 00000000..fbf8c022
--- /dev/null
+++ b/www/schema.json
@@ -0,0 +1,477 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "go2rtc",
+ "type": "object",
+ "additionalProperties": false,
+ "definitions": {
+ "listen": {
+ "type": "string",
+ "anyOf": [
+ {
+ "type": "string",
+ "pattern": ":[0-9]{1,5}$"
+ },
+ {
+ "type": "string",
+ "const": ""
+ }
+ ]
+ },
+ "log_level": {
+ "type": "string",
+ "enum": [
+ "trace",
+ "debug",
+ "info",
+ "warn",
+ "error"
+ ]
+ }
+ },
+ "properties": {
+ "api": {
+ "type": "object",
+ "properties": {
+ "listen": {
+ "default": ":1984",
+ "examples": [
+ "127.0.0.1:8080"
+ ],
+ "$ref": "#/definitions/listen"
+ },
+ "username": {
+ "type": "string",
+ "examples": [
+ "admin"
+ ]
+ },
+ "password": {
+ "type": "string"
+ },
+ "local_auth": {
+ "description": "Will use Auth header from local network",
+ "type": "boolean",
+ "default": false
+ },
+ "base_path": {
+ "type": "string",
+ "default": ""
+ },
+ "static_dir": {
+ "type": "string",
+ "default": ""
+ },
+ "origin": {
+ "type": "string",
+ "default": "*"
+ },
+ "tls_listen": {
+ "$ref": "#/definitions/listen"
+ },
+ "tls_cert": {
+ "type": "string",
+ "examples": [
+ "/etc/ssl/certs/my_certificate.pem"
+ ]
+ },
+ "tls_key": {
+ "type": "string",
+ "examples": [
+ "/etc/ssl/private/my_certificate_key.pem"
+ ]
+ },
+ "unix_listen": {
+ "type": "string",
+ "examples": [
+ "/tmp/go2rtc.sock"
+ ]
+ }
+ }
+ },
+ "ffmpeg": {
+ "type": "object",
+ "properties": {
+ "bin": {
+ "type": "string",
+ "default": "ffmpeg"
+ }
+ },
+ "additionalProperties": {
+ "description": "FFmpeg template",
+ "type": "string"
+ }
+ },
+ "hass": {
+ "type": "object",
+ "properties": {
+ "config": {
+ "type": "string",
+ "examples": [
+ "/config/go2rtc.yaml"
+ ]
+ },
+ "api": {
+ "type": "object",
+ "properties": {
+ "listen": {
+ "default": ":8124",
+ "$ref": "#/definitions/listen"
+ }
+ }
+ }
+ }
+ },
+ "homekit": {
+ "type": "object",
+ "properties": {
+ "pin": {
+ "type": "string",
+ "default": "123-45-678"
+ },
+ "name": {
+ "type": "string",
+ "default": "go2rtc"
+ },
+ "device_id": {
+ "type": "string",
+ "default": ""
+ },
+ "device_private": {
+ "type": "string",
+ "default": ""
+ },
+ "category_id": {
+ "type": "integer",
+ "default": 2
+ },
+ "pairings": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "log": {
+ "type": "object",
+ "properties": {
+ "format": {
+ "type": "string",
+ "default": "color",
+ "enum": [
+ "color",
+ "json",
+ "text"
+ ]
+ },
+ "level": {
+ "description": "Defaul log level",
+ "default": "info",
+ "$ref": "#/definitions/log_level"
+ },
+ "output": {
+ "type": "string",
+ "default": "stdout",
+ "enum": [
+ "",
+ "stdout",
+ "stderr"
+ ]
+ },
+ "time": {
+ "type": "string",
+ "default": "UNIXMS",
+ "anyOf": [
+ {
+ "type": "string",
+ "enum": [
+ "",
+ "UNIXMS",
+ "UNIXMICRO",
+ "UNIXNANO",
+ "2006-01-02T15:04:05Z07:00",
+ "2006-01-02T15:04:05.999999999Z07:00"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "api": {
+ "$ref": "#/definitions/log_level"
+ },
+ "echo": {
+ "$ref": "#/definitions/log_level"
+ },
+ "exec": {
+ "description": "Value `exec: debug` will print stderr",
+ "$ref": "#/definitions/log_level"
+ },
+ "expr": {
+ "$ref": "#/definitions/log_level"
+ },
+ "ffmpeg": {
+ "description": "Will only be displayed with `exec: debug` setting",
+ "default": "error",
+ "$ref": "#/definitions/log_level"
+ },
+ "hass": {
+ "$ref": "#/definitions/log_level"
+ },
+ "hls": {
+ "$ref": "#/definitions/log_level"
+ },
+ "homekit": {
+ "$ref": "#/definitions/log_level"
+ },
+ "mp4": {
+ "$ref": "#/definitions/log_level"
+ },
+ "ngrok": {
+ "$ref": "#/definitions/log_level"
+ },
+ "onvif": {
+ "$ref": "#/definitions/log_level"
+ },
+ "rtmp": {
+ "$ref": "#/definitions/log_level"
+ },
+ "rtsp": {
+ "$ref": "#/definitions/log_level"
+ },
+ "streams": {
+ "$ref": "#/definitions/log_level"
+ },
+ "webrtc": {
+ "$ref": "#/definitions/log_level"
+ },
+ "webtorrent": {
+ "$ref": "#/definitions/log_level"
+ }
+ }
+ },
+ "ngrok": {
+ "type": "object",
+ "properties": {
+ "command": {
+ "description": "ngrok start --all --config ngrok.yaml",
+ "type": "string"
+ }
+ }
+ },
+ "publish": {
+ "type": "object",
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "type": "string",
+ "examples": [
+ "rtmp://xxx.rtmp.youtube.com/live2/xxxx-xxxx-xxxx-xxxx-xxxx",
+ "rtmps://xxx-x.rtmp.t.me/s/xxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxx"
+ ]
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ }
+ },
+ "rtmp": {
+ "type": "object",
+ "properties": {
+ "listen": {
+ "examples": [
+ ":1935"
+ ],
+ "$ref": "#/definitions/listen"
+ }
+ }
+ },
+ "rtsp": {
+ "type": "object",
+ "properties": {
+ "listen": {
+ "default": ":8554",
+ "$ref": "#/definitions/listen"
+ },
+ "username": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "default_query": {
+ "type": "string",
+ "default": ""
+ },
+ "pkt_size": {
+ "type": "integer",
+ "default": 0
+ }
+ }
+ },
+ "srtp": {
+ "type": "object",
+ "properties": {
+ "listen": {
+ "default": ":8443",
+ "$ref": "#/definitions/listen"
+ }
+ }
+ },
+ "streams": {
+ "type": "object",
+ "additionalProperties": {
+ "title": "Stream",
+ "anyOf": [
+ {
+ "description": "Source",
+ "type": "string",
+ "examples": [
+ "rtsp://username:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif",
+ "rtsp://username:password@192.168.1.123/stream1",
+ "rtsp://username:password@192.168.1.123/h264Preview_01_main",
+ "rtmp://192.168.1.123/bcs/channel0_main.bcs?channel=0&stream=0&user=username&password=password",
+ "http://192.168.1.123/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=username&password=password",
+ "http://username:password@192.168.1.123/cgi-bin/snapshot.cgi?channel=1",
+ "ffmpeg:media.mp4#video=h264#hardware#width=1920#height=1080#rotate=180#audio=copy",
+ "ffmpeg:virtual?video=testsrc&size=4K#video=h264#hardware#bitrate=50M",
+ "bubble://username:password@192.168.1.123:34567/bubble/live?ch=0&stream=0",
+ "dvrip://username:password@192.168.1.123:34567?channel=0&subtype=0",
+ "exec:ffmpeg -re -i media.mp4 -c copy -rtsp_transport tcp -f rtsp {output}",
+ "isapi://username:password@192.168.1.123:80/",
+ "kasa://username:password@192.168.1.123:19443/https/stream/mixed",
+ "onvif://username:password@192.168.1.123:80?subtype=0",
+ "tapo://password@192.168.1.123:8800?channel=0&subtype=0",
+ "webtorrent:?share=xxx&pwd=xxx"
+ ]
+ },
+ {
+ "type": "array",
+ "items": {
+ "description": "Source",
+ "type": "string"
+ }
+ }
+ ]
+ }
+ },
+ "webrtc": {
+ "type": "object",
+ "properties": {
+ "listen": {
+ "default": ":8555",
+ "$ref": "#/definitions/listen"
+ },
+ "candidates": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": [
+ "192.168.1.123",
+ "stun:stun.l.google.com:19302"
+ ]
+ }
+ },
+ "ice_servers": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "urls": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": [
+ "stun:stun.l.google.com:19302",
+ "turn:123.123.123.123:3478"
+ ]
+ }
+ },
+ "username": {
+ "type": "string"
+ },
+ "credential": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "filters": {
+ "type": "object",
+ "properties": {
+ "candidates": {
+ "description": "Keep only these candidates",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "interfaces": {
+ "description": "Keep only these interfaces",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ips": {
+ "description": "Keep only these IP-addresses",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "networks": {
+ "description": "Use only these network types",
+ "type": "array",
+ "items": {
+ "enum": [
+ "tcp4",
+ "tcp6",
+ "udp4",
+ "udp6"
+ ],
+ "type": "string"
+ }
+ },
+ "udp_ports": {
+ "description": "Use only these UDP ports range [min, max]",
+ "type": "array",
+ "items": {
+ "type": "integer"
+ },
+ "maxItems": 2,
+ "minItems": 2
+ }
+ }
+ }
+ }
+ },
+ "webtorrent": {
+ "type": "object",
+ "properties": {
+ "trackers": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "shares": {
+ "type": "object",
+ "properties": {
+ "pwd": {
+ "type": "string"
+ },
+ "src": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/www/static.go b/www/static.go
index 01f50906..064fec36 100644
--- a/www/static.go
+++ b/www/static.go
@@ -4,4 +4,5 @@ import "embed"
//go:embed *.html
//go:embed *.js
+//go:embed *.json
var Static embed.FS