mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2026-04-22 15:47:06 +08:00
154 lines
5.0 KiB
Markdown
154 lines
5.0 KiB
Markdown
# Expr
|
|
|
|
[`new in v1.8.2`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.2)
|
|
|
|
[Expr](https://github.com/antonmedv/expr) - expression language and expression evaluation for Go.
|
|
|
|
- [language definition](https://expr.medv.io/docs/Language-Definition) - takes best from JS, Python, Jinja2 syntax
|
|
- your expression should return a link of any supported source
|
|
- expression supports multiple operation, but:
|
|
- all operations must be separated by a semicolon
|
|
- all operations, except the last one, must declare a new variable (`let s = "abc";`)
|
|
- the last operation should return a string
|
|
- go2rtc supports additional functions:
|
|
- `fetch` - JS-like HTTP requests
|
|
- `match` - JS-like RegExp queries
|
|
|
|
## Fetch examples
|
|
|
|
Multiple fetch requests are executed within a single session. They share the same cookie.
|
|
|
|
**HTTP GET**
|
|
|
|
```js
|
|
var r = fetch('https://example.org/products.json');
|
|
```
|
|
|
|
**HTTP POST JSON**
|
|
|
|
```js
|
|
var r = fetch('https://example.org/post', {
|
|
method: 'POST',
|
|
// Content-Type: application/json will be set automatically
|
|
json: {username: 'example'}
|
|
});
|
|
```
|
|
|
|
**HTTP POST Form**
|
|
|
|
```js
|
|
var r = fetch('https://example.org/post', {
|
|
method: 'POST',
|
|
// Content-Type: application/x-www-form-urlencoded will be set automatically
|
|
data: {username: 'example', password: 'password'}
|
|
});
|
|
```
|
|
|
|
## Script examples
|
|
|
|
**Two way audio for Dahua VTO**
|
|
|
|
```yaml
|
|
streams:
|
|
dahua_vto: |
|
|
expr:
|
|
let host = 'admin:password@192.168.1.123';
|
|
|
|
var r = fetch('http://' + host + '/cgi-bin/configManager.cgi?action=setConfig&Encode[0].MainFormat[0].Audio.Compression=G.711A&Encode[0].MainFormat[0].Audio.Frequency=8000');
|
|
|
|
'rtsp://' + host + '/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif'
|
|
```
|
|
|
|
**dom.ru**
|
|
|
|
You can get credentials from https://github.com/ad/domru
|
|
|
|
```yaml
|
|
streams:
|
|
dom_ru: |
|
|
expr:
|
|
let camera = '***';
|
|
let token = '***';
|
|
let operator = '***';
|
|
|
|
fetch('https://myhome.proptech.ru/rest/v1/forpost/cameras/' + camera + '/video', {
|
|
headers: {
|
|
'Authorization': 'Bearer ' + token,
|
|
'User-Agent': 'Google sdkgphone64x8664 | Android 14 | erth | 8.26.0 (82600010) | 0 | 0 | 0',
|
|
'Operator': operator
|
|
}
|
|
}).json().data.URL
|
|
```
|
|
|
|
**dom.ufanet.ru**
|
|
|
|
```yaml
|
|
streams:
|
|
ufanet_ru: |
|
|
expr:
|
|
let username = '***';
|
|
let password = '***';
|
|
let cameraid = '***';
|
|
|
|
let r1 = fetch('https://ucams.ufanet.ru/api/internal/login/', {
|
|
method: 'POST',
|
|
data: {username: username, password: password}
|
|
});
|
|
let r2 = fetch('https://ucams.ufanet.ru/api/v0/cameras/this/?lang=ru', {
|
|
method: 'POST',
|
|
json: {'fields': ['token_l', 'server'], 'token_l_ttl': 3600, 'numbers': [cameraid]},
|
|
}).json().results[0];
|
|
|
|
'rtsp://' + r2.server.domain + '/' + r2.number + '?token=' + r2.token_l
|
|
```
|
|
|
|
**Parse HLS files from Apple**
|
|
|
|
Same example in two languages - python and expr.
|
|
|
|
```yaml
|
|
streams:
|
|
example_python: |
|
|
echo:python -c 'from urllib.request import urlopen; import re
|
|
|
|
# url1 = "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8"
|
|
html1 = urlopen("https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html").read().decode("utf-8")
|
|
url1 = re.search(r"https.+?m3u8", html1)[0]
|
|
|
|
# url2 = "gear1/prog_index.m3u8"
|
|
html2 = urlopen(url1).read().decode("utf-8")
|
|
url2 = re.search(r"^[a-z0-1/_]+\.m3u8$", html2, flags=re.MULTILINE)[0]
|
|
|
|
# url3 = "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/gear1/prog_index.m3u8"
|
|
url3 = url1[:url1.rindex("/")+1] + url2
|
|
|
|
print("ffmpeg:" + url3 + "#video=copy")'
|
|
|
|
example_expr: |
|
|
expr:
|
|
|
|
let html1 = fetch("https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html").text;
|
|
let url1 = match(html1, "https.+?m3u8")[0];
|
|
|
|
let html2 = fetch(url1).text;
|
|
let url2 = match(html2, "^[a-z0-1/_]+\\.m3u8$", "m")[0];
|
|
|
|
let url3 = url1[:lastIndexOf(url1, "/")+1] + url2;
|
|
|
|
"ffmpeg:" + url3 + "#video=copy"
|
|
```
|
|
|
|
## Comparison
|
|
|
|
| expr | python | js |
|
|
|------------------------------|----------------------------|--------------------------------|
|
|
| let x = 1; | x = 1 | let x = 1 |
|
|
| {a: 1, b: 2} | {"a": 1, "b": 2} | {a: 1, b: 2} |
|
|
| let r = fetch(url, {method}) | r = request(method, url) | r = await fetch(url, {method}) |
|
|
| r.ok | r.ok | r.ok |
|
|
| r.status | r.status_code | r.status |
|
|
| r.text | r.text | await r.text() |
|
|
| r.json() | r.json() | await r.json() |
|
|
| r.headers | r.headers | r.headers |
|
|
| let m = match(text, "abc") | m = re.search("abc", text) | let m = text.match(/abc/) |
|