mirror of
https://github.com/openlibrecommunity/olcrtc.git
synced 2026-06-07 21:04:42 +00:00
Remove Docker support and reduce runtime load
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
Dockerfile
|
||||
docker-compose*.yml
|
||||
|
||||
code/
|
||||
doc/
|
||||
asset/
|
||||
|
||||
*.log
|
||||
*.tmp
|
||||
tmp/
|
||||
|
||||
olcrtc
|
||||
build/
|
||||
dist/
|
||||
coverage.out
|
||||
GEMINI.md
|
||||
10
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
10
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -31,7 +31,7 @@ body:
|
||||
id: version
|
||||
attributes:
|
||||
label: Версия olcrtc
|
||||
description: Тег релиза, имя ветки и git commit (`git rev-parse --short HEAD`). Если собирал из docker - пиши тег образа.
|
||||
description: Тег релиза, имя ветки и git commit (`git rev-parse --short HEAD`).
|
||||
placeholder: "main @ a1b2c3d / v0.x.y / refactor/universal-carrier @ ef01234"
|
||||
validations:
|
||||
required: true
|
||||
@@ -42,8 +42,8 @@ body:
|
||||
label: Способ сборки/запуска
|
||||
options:
|
||||
- Native
|
||||
- Docker / docker compose
|
||||
- Podman / script
|
||||
- Native binary
|
||||
- Mobile / gomobile
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
@@ -170,8 +170,6 @@ body:
|
||||
description: |
|
||||
Полные логи с момента запуска до момента ошибки.
|
||||
Если запуск через systemd - `journalctl -u olcrtc -n 500 --no-pager`.
|
||||
Если docker - `docker logs <container>`.
|
||||
Если запуск через podman - `podman logs -f <container> `.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
@@ -205,6 +203,6 @@ body:
|
||||
id: extra
|
||||
attributes:
|
||||
label: Дополнительно
|
||||
description: Что ещё может быть полезно - версия podman/docker, нестандартный конфиг (failover, traffic shaping, lifecycle), временные паттерны (бьёт раз в сутки, после сна и т.п.), известные обходы.
|
||||
description: Что ещё может быть полезно - нестандартный конфиг (failover, traffic shaping, lifecycle), временные паттерны (бьёт раз в сутки, после сна и т.п.), известные обходы.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -38,7 +38,7 @@
|
||||
- [ ] session / app (`internal/app/session`, `pkg/`)
|
||||
- [ ] config / CLI / URI / sub
|
||||
- [ ] mobile (`mobile/`)
|
||||
- [ ] CI / Docker / mage
|
||||
- [ ] CI / mage
|
||||
- [ ] docs / examples
|
||||
- [ ] другое:
|
||||
|
||||
|
||||
59
Dockerfile
59
Dockerfile
@@ -1,59 +0,0 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
|
||||
ARG GO_VERSION=1.26
|
||||
ARG ALPINE_VERSION=3.22
|
||||
|
||||
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS build
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
RUN apk add --no-cache ca-certificates git
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
go mod download
|
||||
|
||||
COPY . .
|
||||
|
||||
ARG TARGETOS=linux
|
||||
ARG TARGETARCH=amd64
|
||||
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \
|
||||
go build -trimpath -ldflags="-s -w" -o /out/olcrtc ./cmd/olcrtc
|
||||
|
||||
FROM alpine:${ALPINE_VERSION} AS runtime
|
||||
|
||||
RUN apk add --no-cache ca-certificates ffmpeg tzdata && \
|
||||
addgroup -S olcrtc && \
|
||||
mkdir -p /usr/share/olcrtc /var/lib/olcrtc && \
|
||||
adduser -S -D -h /var/lib/olcrtc -s /sbin/nologin -G olcrtc olcrtc && \
|
||||
chown -R olcrtc:olcrtc /usr/share/olcrtc /var/lib/olcrtc
|
||||
|
||||
COPY --chown=olcrtc:olcrtc data /usr/share/olcrtc
|
||||
COPY --from=build /out/olcrtc /usr/local/bin/olcrtc
|
||||
COPY script/docker/olcrtc-entrypoint.sh /usr/local/bin/olcrtc-entrypoint
|
||||
COPY script/docker/olcrtc-healthcheck.sh /usr/local/bin/olcrtc-healthcheck
|
||||
|
||||
RUN chmod 0755 /usr/local/bin/olcrtc /usr/local/bin/olcrtc-entrypoint /usr/local/bin/olcrtc-healthcheck
|
||||
|
||||
USER olcrtc:olcrtc
|
||||
WORKDIR /var/lib/olcrtc
|
||||
|
||||
ENV OLCRTC_MODE=srv \
|
||||
OLCRTC_CARRIER= \
|
||||
OLCRTC_TRANSPORT=datachannel \
|
||||
OLCRTC_DATA_DIR=/usr/share/olcrtc \
|
||||
OLCRTC_DNS=8.8.8.8:53 \
|
||||
OLCRTC_KEY_FILE=/var/lib/olcrtc/key.hex \
|
||||
OLCRTC_SOCKS_HOST=127.0.0.1 \
|
||||
OLCRTC_SOCKS_PORT=8808 \
|
||||
OLCRTC_FFMPEG=ffmpeg
|
||||
|
||||
VOLUME ["/var/lib/olcrtc"]
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=20s --retries=3 \
|
||||
CMD ["/usr/local/bin/olcrtc-healthcheck"]
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/olcrtc-entrypoint"]
|
||||
@@ -164,8 +164,8 @@ func TestRunWithArgsAppliesTransportDefaults(t *testing.T) {
|
||||
oldRunSession := runSession
|
||||
t.Cleanup(func() { runSession = oldRunSession })
|
||||
runSession = func(_ context.Context, cfg session.Config) error {
|
||||
if cfg.VP8.FPS != 60 || cfg.VP8.BatchSize != 64 {
|
||||
t.Errorf("VP8 defaults = fps %d batch %d, want 60/64", cfg.VP8.FPS, cfg.VP8.BatchSize)
|
||||
if cfg.VP8.FPS != 30 || cfg.VP8.BatchSize != 64 {
|
||||
t.Errorf("VP8 defaults = fps %d batch %d, want 30/64", cfg.VP8.FPS, cfg.VP8.BatchSize)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -204,8 +204,8 @@ func TestRunWithArgsFailoverProfiles(t *testing.T) {
|
||||
var seen []string
|
||||
runSession = func(_ context.Context, cfg session.Config) error {
|
||||
seen = append(seen, cfg.Auth+"/"+cfg.Transport)
|
||||
if cfg.Auth == "wbstream" && (cfg.VP8.FPS != 60 || cfg.VP8.BatchSize != 64) {
|
||||
t.Errorf("VP8 defaults = fps %d batch %d, want 60/64", cfg.VP8.FPS, cfg.VP8.BatchSize)
|
||||
if cfg.Auth == "wbstream" && (cfg.VP8.FPS != 30 || cfg.VP8.BatchSize != 64) {
|
||||
t.Errorf("VP8 defaults = fps %d batch %d, want 30/64", cfg.VP8.FPS, cfg.VP8.BatchSize)
|
||||
}
|
||||
return errBoom
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
services:
|
||||
olcrtc-client:
|
||||
build:
|
||||
context: .
|
||||
image: olcrtc/client:local
|
||||
container_name: olcrtc-client
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
environment:
|
||||
OLCRTC_MODE: cnc
|
||||
OLCRTC_CARRIER: "${OLCRTC_CARRIER:?set OLCRTC_CARRIER (jitsi, telemost, wbstream, none)}"
|
||||
OLCRTC_TRANSPORT: "${OLCRTC_TRANSPORT:-datachannel}"
|
||||
OLCRTC_ROOM_ID: "${OLCRTC_ROOM_ID:?set OLCRTC_ROOM_ID to the server room}"
|
||||
OLCRTC_KEY: "${OLCRTC_KEY:?set OLCRTC_KEY to the server encryption key}"
|
||||
OLCRTC_KEY_FILE: "${OLCRTC_KEY_FILE:-/var/lib/olcrtc/key.hex}"
|
||||
OLCRTC_DNS: "${OLCRTC_DNS:-8.8.8.8:53}"
|
||||
OLCRTC_SOCKS_HOST: "${OLCRTC_SOCKS_HOST:-127.0.0.1}"
|
||||
OLCRTC_SOCKS_PORT: "${OLCRTC_SOCKS_PORT:-8808}"
|
||||
OLCRTC_SOCKS_USER: "${OLCRTC_SOCKS_USER:-}"
|
||||
OLCRTC_SOCKS_PASS: "${OLCRTC_SOCKS_PASS:-}"
|
||||
OLCRTC_VIDEO_W: "${OLCRTC_VIDEO_W:-0}"
|
||||
OLCRTC_VIDEO_H: "${OLCRTC_VIDEO_H:-0}"
|
||||
OLCRTC_VIDEO_FPS: "${OLCRTC_VIDEO_FPS:-0}"
|
||||
OLCRTC_VIDEO_BITRATE: "${OLCRTC_VIDEO_BITRATE:-}"
|
||||
OLCRTC_VIDEO_HW: "${OLCRTC_VIDEO_HW:-none}"
|
||||
OLCRTC_VIDEO_CODEC: "${OLCRTC_VIDEO_CODEC:-qrcode}"
|
||||
OLCRTC_VIDEO_QR_SIZE: "${OLCRTC_VIDEO_QR_SIZE:-0}"
|
||||
OLCRTC_VIDEO_QR_RECOVERY: "${OLCRTC_VIDEO_QR_RECOVERY:-low}"
|
||||
OLCRTC_VIDEO_TILE_MODULE: "${OLCRTC_VIDEO_TILE_MODULE:-0}"
|
||||
OLCRTC_VIDEO_TILE_RS: "${OLCRTC_VIDEO_TILE_RS:-0}"
|
||||
OLCRTC_VP8_FPS: "${OLCRTC_VP8_FPS:-0}"
|
||||
OLCRTC_VP8_BATCH: "${OLCRTC_VP8_BATCH:-0}"
|
||||
OLCRTC_SEI_FPS: "${OLCRTC_SEI_FPS:-0}"
|
||||
OLCRTC_SEI_BATCH: "${OLCRTC_SEI_BATCH:-0}"
|
||||
OLCRTC_SEI_FRAG: "${OLCRTC_SEI_FRAG:-0}"
|
||||
OLCRTC_SEI_ACK: "${OLCRTC_SEI_ACK:-0}"
|
||||
OLCRTC_DEBUG: "${OLCRTC_DEBUG:-false}"
|
||||
volumes:
|
||||
- olcrtc-client-state:/var/lib/olcrtc
|
||||
init: true
|
||||
|
||||
volumes:
|
||||
olcrtc-client-state:
|
||||
@@ -1,40 +0,0 @@
|
||||
services:
|
||||
olcrtc-server:
|
||||
build:
|
||||
context: .
|
||||
image: olcrtc/server:local
|
||||
container_name: olcrtc-server
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
OLCRTC_MODE: srv
|
||||
OLCRTC_CARRIER: "${OLCRTC_CARRIER:?set OLCRTC_CARRIER (jitsi, telemost, wbstream, none)}"
|
||||
OLCRTC_TRANSPORT: "${OLCRTC_TRANSPORT:-datachannel}"
|
||||
OLCRTC_ROOM_ID: "${OLCRTC_ROOM_ID:-}"
|
||||
OLCRTC_KEY: "${OLCRTC_KEY:-}"
|
||||
OLCRTC_KEY_FILE: "${OLCRTC_KEY_FILE:-/var/lib/olcrtc/key.hex}"
|
||||
OLCRTC_DNS: "${OLCRTC_DNS:-8.8.8.8:53}"
|
||||
OLCRTC_SOCKS_PROXY: "${OLCRTC_SOCKS_PROXY:-}"
|
||||
OLCRTC_SOCKS_PROXY_PORT: "${OLCRTC_SOCKS_PROXY_PORT:-1080}"
|
||||
OLCRTC_VIDEO_W: "${OLCRTC_VIDEO_W:-0}"
|
||||
OLCRTC_VIDEO_H: "${OLCRTC_VIDEO_H:-0}"
|
||||
OLCRTC_VIDEO_FPS: "${OLCRTC_VIDEO_FPS:-0}"
|
||||
OLCRTC_VIDEO_BITRATE: "${OLCRTC_VIDEO_BITRATE:-}"
|
||||
OLCRTC_VIDEO_HW: "${OLCRTC_VIDEO_HW:-none}"
|
||||
OLCRTC_VIDEO_CODEC: "${OLCRTC_VIDEO_CODEC:-qrcode}"
|
||||
OLCRTC_VIDEO_QR_SIZE: "${OLCRTC_VIDEO_QR_SIZE:-0}"
|
||||
OLCRTC_VIDEO_QR_RECOVERY: "${OLCRTC_VIDEO_QR_RECOVERY:-low}"
|
||||
OLCRTC_VIDEO_TILE_MODULE: "${OLCRTC_VIDEO_TILE_MODULE:-0}"
|
||||
OLCRTC_VIDEO_TILE_RS: "${OLCRTC_VIDEO_TILE_RS:-0}"
|
||||
OLCRTC_VP8_FPS: "${OLCRTC_VP8_FPS:-0}"
|
||||
OLCRTC_VP8_BATCH: "${OLCRTC_VP8_BATCH:-0}"
|
||||
OLCRTC_SEI_FPS: "${OLCRTC_SEI_FPS:-0}"
|
||||
OLCRTC_SEI_BATCH: "${OLCRTC_SEI_BATCH:-0}"
|
||||
OLCRTC_SEI_FRAG: "${OLCRTC_SEI_FRAG:-0}"
|
||||
OLCRTC_SEI_ACK: "${OLCRTC_SEI_ACK:-0}"
|
||||
OLCRTC_DEBUG: "${OLCRTC_DEBUG:-false}"
|
||||
volumes:
|
||||
- olcrtc-state:/var/lib/olcrtc
|
||||
init: true
|
||||
|
||||
volumes:
|
||||
olcrtc-state:
|
||||
@@ -188,7 +188,6 @@ data: data
|
||||
| `internal/client` | SOCKS5 listener, client-side smux |
|
||||
| `internal/control` | liveness ping/pong |
|
||||
| `internal/supervisor` | failover profiles |
|
||||
| `script` | интерактивные launchers и Docker entrypoint |
|
||||
| `docs` | документация и примеры YAML |
|
||||
|
||||
## Сборка
|
||||
@@ -201,11 +200,9 @@ mage cross
|
||||
mage test
|
||||
mage lint
|
||||
mage mobile
|
||||
mage docker
|
||||
mage podman
|
||||
```
|
||||
|
||||
Go версия в сборочных скриптах: `1.25`. Для `videochannel` нужен `ffmpeg`; для `codec: tile` требуется разрешение `1080x1080`.
|
||||
Go версия: `1.26+`. Для `videochannel` нужен `ffmpeg`; для `codec: tile` требуется разрешение `1080x1080`.
|
||||
|
||||
## Public API
|
||||
|
||||
|
||||
148
docs/docker.md
148
docs/docker.md
@@ -1,148 +0,0 @@
|
||||
<div align="center">
|
||||
|
||||
<img src="https://github.com/openlibrecommunity/material/blob/master/olcrtc.png" width="250" height="250">
|
||||
|
||||

|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
# Локальная настройка Docker
|
||||
|
||||
> **Важно:** Обязательно проверяйте, есть ли сервис видеозвонков у вас в белых списках. Если его там нет - используйте другой. Список всех сервисов в белых списках скоро будет опубликован.
|
||||
|
||||
> **Jitsi-провайдер:** если используете `jitsi`, выбирайте сервер в зависимости от того, что доступно в вашей сети:
|
||||
> - `https://meet.small-dm.ru/`
|
||||
> - `https://meet1.arbitr.ru/`
|
||||
> - `https://meet.handyweb.org/`
|
||||
>
|
||||
> Откройте в браузере и используйте тот, который работает.
|
||||
|
||||
|
||||
Здесь описан один из способов запуска сервера olcrtc с локальной конфигурацией Docker.
|
||||
|
||||
## Идея
|
||||
|
||||
- держать изменяемые Docker-файлы в скрытой папке `.local`
|
||||
- хранить конфигурационные файлы вне Git, в папке `.local`
|
||||
- позволять пользователям обновлять репозиторий обычным `git pull`
|
||||
|
||||
---
|
||||
|
||||
## Шаг 1: Клонирование репозитория
|
||||
|
||||
```bash
|
||||
git clone https://github.com/openlibrecommunity/olcrtc.git
|
||||
cd olcrtc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Шаг 2: Обновление до последней версии
|
||||
|
||||
Чтобы получить новую версию из upstream:
|
||||
|
||||
```bash
|
||||
git pull https://github.com/openlibrecommunity/olcrtc.git --recurse-submodules
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Шаг 3: Папка для локальных конфигураций
|
||||
|
||||
Создайте директорию `.local` в корне репозитория:
|
||||
|
||||
```bash
|
||||
mkdir -p .local
|
||||
```
|
||||
|
||||
Эта папка должна содержать файлы, которые будут использоваться только на вашем сервере.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 4: Скопируйте docker-compose.yml в `.local`
|
||||
|
||||
Скопируйте файл `docker-compose.server.yml`, чтобы ваша локальная версия не перезаписывалась при следующем обновлении репозитория через `git pull`:
|
||||
|
||||
```bash
|
||||
cp docker-compose.server.yml .local/docker-compose.server.yml
|
||||
```
|
||||
|
||||
Если файл `docker-compose.server.yml` позже изменится, скопируйте его снова этой же командой после `git pull`.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 5: Создайте локальный файл окружения
|
||||
|
||||
Создайте `.local/.env` и заполните значения в соответствии с выбранным типом подключения.
|
||||
|
||||
Пример можно найти в `docs/examples/server/.env.telemost.server.example`.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 6: Запуск OLCRTC
|
||||
|
||||
Запуск контейнеризированного сервера используя `docker-compose.server.yml` и локальный `.env`:
|
||||
|
||||
```bash
|
||||
docker compose -f .local/docker-compose.server.yml --env-file .local/.env up -d
|
||||
```
|
||||
|
||||
Проверка состояния контейнера:
|
||||
|
||||
```bash
|
||||
docker compose -f .local/docker-compose.server.yml --env-file .local/.env ps
|
||||
```
|
||||
|
||||
Просмотр логов контейнера:
|
||||
|
||||
```bash
|
||||
docker compose -f .local/docker-compose.server.yml --env-file .local/.env logs -f
|
||||
docker logs olcrtc-server
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Шаг 7: Обновление контейнера
|
||||
|
||||
Получите новую версию репозитория:
|
||||
|
||||
```bash
|
||||
git pull https://github.com/openlibrecommunity/olcrtc.git
|
||||
```
|
||||
|
||||
После каждого обновления сравните новый и старый файл:
|
||||
|
||||
```bash
|
||||
diff -wy .local/docker-compose.server.yml docker-compose.server.yml
|
||||
```
|
||||
|
||||
Если есть отличия, скопируйте файл из корня в папку `.local`:
|
||||
|
||||
```bash
|
||||
cp docker-compose.server.yml .local/docker-compose.server.yml
|
||||
```
|
||||
|
||||
Затем перезапустите контейнер:
|
||||
|
||||
```bash
|
||||
docker compose -f .local/docker-compose.server.yml down
|
||||
docker compose -f .local/docker-compose.server.yml --env-file .local/.env up -d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Примечания
|
||||
|
||||
- Храните все локальные Docker-файлы внутри отдельной папки `.local`.
|
||||
- Не добавляйте `.local` в репозиторий (она должна быть в `.gitignore`).
|
||||
- Держите общую документацию в `docs/`, а специфичные настройки в `.local`.
|
||||
|
||||
---
|
||||
|
||||
Используешь скрипты вместо Docker? -> [Быстрый старт](fast.md)
|
||||
|
||||
Хочешь собрать руками без контейнеров? -> [Мануальная сборка](manual.md)
|
||||
|
||||
Все настройки и матрица совместимости -> [settings.md](settings.md)
|
||||
@@ -33,7 +33,7 @@ socks:
|
||||
pass: ""
|
||||
|
||||
sei:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
fragment_size: 900
|
||||
ack_timeout_ms: 2000
|
||||
|
||||
@@ -33,7 +33,7 @@ socks:
|
||||
pass: ""
|
||||
|
||||
vp8:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
|
||||
data: data
|
||||
|
||||
@@ -31,7 +31,7 @@ socks:
|
||||
pass: ""
|
||||
|
||||
sei:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
fragment_size: 900
|
||||
ack_timeout_ms: 2000
|
||||
|
||||
@@ -31,7 +31,7 @@ socks:
|
||||
pass: ""
|
||||
|
||||
vp8:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
|
||||
data: data
|
||||
|
||||
@@ -31,7 +31,7 @@ socks:
|
||||
pass: ""
|
||||
|
||||
sei:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
fragment_size: 900
|
||||
ack_timeout_ms: 2000
|
||||
|
||||
@@ -31,7 +31,7 @@ socks:
|
||||
pass: ""
|
||||
|
||||
vp8:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
|
||||
data: data
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
OLCRTC_MODE=srv
|
||||
OLCRTC_CARRIER=telemost
|
||||
OLCRTC_TRANSPORT=vp8channel
|
||||
|
||||
# Telemost-specific session values.
|
||||
OLCRTC_ROOM_ID=12345678901234
|
||||
OLCRTC_CLIENT_ID=default
|
||||
OLCRTC_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
||||
OLCRTC_KEY_FILE=/var/lib/olcrtc/key.hex
|
||||
|
||||
# Network and runtime defaults used by the server compose.
|
||||
OLCRTC_DNS=8.8.8.8:53
|
||||
OLCRTC_SOCKS_PROXY=
|
||||
OLCRTC_SOCKS_PROXY_PORT=1080
|
||||
OLCRTC_DEBUG=false
|
||||
|
||||
# Video-channel settings accepted by docker-compose.server.yml.
|
||||
OLCRTC_VIDEO_W=0
|
||||
OLCRTC_VIDEO_H=0
|
||||
OLCRTC_VIDEO_FPS=0
|
||||
OLCRTC_VIDEO_BITRATE=
|
||||
OLCRTC_VIDEO_HW=none
|
||||
OLCRTC_VIDEO_CODEC=qrcode
|
||||
OLCRTC_VIDEO_QR_SIZE=0
|
||||
OLCRTC_VIDEO_QR_RECOVERY=low
|
||||
OLCRTC_VIDEO_TILE_MODULE=0
|
||||
OLCRTC_VIDEO_TILE_RS=0
|
||||
|
||||
# VP8 transport settings.
|
||||
OLCRTC_VP8_FPS=60
|
||||
OLCRTC_VP8_BATCH=64
|
||||
|
||||
# SEI transport settings.
|
||||
OLCRTC_SEI_FPS=0
|
||||
OLCRTC_SEI_BATCH=0
|
||||
OLCRTC_SEI_FRAG=0
|
||||
OLCRTC_SEI_ACK=0
|
||||
@@ -34,7 +34,7 @@ socks:
|
||||
proxy_pass: ""
|
||||
|
||||
sei:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
fragment_size: 900
|
||||
ack_timeout_ms: 2000
|
||||
|
||||
@@ -34,7 +34,7 @@ socks:
|
||||
proxy_pass: ""
|
||||
|
||||
vp8:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
|
||||
data: data
|
||||
|
||||
@@ -32,7 +32,7 @@ socks:
|
||||
proxy_pass: ""
|
||||
|
||||
sei:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
fragment_size: 900
|
||||
ack_timeout_ms: 2000
|
||||
|
||||
@@ -32,7 +32,7 @@ socks:
|
||||
proxy_pass: ""
|
||||
|
||||
vp8:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
|
||||
data: data
|
||||
|
||||
@@ -32,7 +32,7 @@ socks:
|
||||
proxy_pass: ""
|
||||
|
||||
sei:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
fragment_size: 900
|
||||
ack_timeout_ms: 2000
|
||||
|
||||
@@ -32,7 +32,7 @@ socks:
|
||||
proxy_pass: ""
|
||||
|
||||
vp8:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
|
||||
data: data
|
||||
|
||||
410
docs/fast.md
410
docs/fast.md
@@ -7,407 +7,145 @@
|
||||
|
||||
</div>
|
||||
|
||||
# Быстрый старт
|
||||
|
||||
# Быстрый старт (через скрипты)
|
||||
> **Важно:** Обязательно проверяйте, есть ли сервис видеозвонков у вас в белых списках. Если его там нет - используйте другой.
|
||||
|
||||
> **Важно:** Обязательно проверяйте, есть ли сервис видеозвонков у вас в белых списках. Если его там нет - используйте другой. Список всех сервисов в белых списках скоро будет опубликован.
|
||||
Этот способ запускает `olcrtc` как обычный нативный бинарник. Нужны Go 1.26+, mage, git и curl.
|
||||
|
||||
|
||||
Этот способ самый простой. Все запускается в контейнере [Podman](https://ru.wikipedia.org/wiki/Podman).
|
||||
Скрипт всё сделает сам: скачает [исходники](https://github.com/openlibrecommunity/olcrtc), соберёт в контейнере, запустит.
|
||||
|
||||
Проект в бете. По проблемам: t.me/openlibrecommunity
|
||||
|
||||
---
|
||||
|
||||
## Что нужно установить
|
||||
|
||||
### git
|
||||
## Установить зависимости
|
||||
|
||||
```sh
|
||||
apt install git # Debian / Ubuntu / Mint
|
||||
pacman -S git # Arch / CacheOS / Manjaro
|
||||
dnf install git # Fedora / RHEL / CentOS
|
||||
apt install git curl # Debian / Ubuntu / Mint
|
||||
pacman -S git curl # Arch / CachyOS / Manjaro
|
||||
dnf install git curl # Fedora / RHEL / CentOS
|
||||
```
|
||||
|
||||
### podman
|
||||
Установи Go 1.26+ и mage:
|
||||
|
||||
```sh
|
||||
apt install podman # Debian / Ubuntu / Mint
|
||||
pacman -S podman # Arch / CacheOS / Manjaro
|
||||
dnf install podman # Fedora / RHEL / CentOS
|
||||
go install github.com/magefile/mage@latest
|
||||
echo 'export PATH="$HOME/go/bin:$PATH"' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
### curl
|
||||
Если на машине меньше 4 ГБ RAM, включи swap перед сборкой:
|
||||
|
||||
```sh
|
||||
apt install curl # Debian / Ubuntu / Mint
|
||||
pacman -S curl # Arch / CacheOS / Manjaro
|
||||
dnf install curl # Fedora / RHEL / CentOS
|
||||
```
|
||||
|
||||
### swap (ОЗУ)
|
||||
|
||||
Если у вас меньше 4ГБ оперативной памяти, сборка может вылетать. **Обязательно включите SWAP**:
|
||||
|
||||
```bash
|
||||
sudo fallocate -l 4G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Шаг 1: Скачать репозиторий
|
||||
## Собрать
|
||||
|
||||
```sh
|
||||
git clone https://github.com/openlibrecommunity/olcrtc --recurse-submodules
|
||||
cd olcrtc
|
||||
mage build
|
||||
```
|
||||
|
||||
<img src="asset/gitclone.png" alt="speedtest" width="800">
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Шаг 2: Запустить сервер
|
||||
|
||||
На машине, через которую должен идти трафик (VPS, сервер за рубежом, домашний ПК):
|
||||
Бинарник появится в `build/`, например:
|
||||
|
||||
```sh
|
||||
./script/srv.sh
|
||||
./build/olcrtc-linux-amd64
|
||||
```
|
||||
|
||||
#### Флаги `srv.sh`
|
||||
## Сгенерировать ключ
|
||||
|
||||
| Флаг | Что делает |
|
||||
|---|---|
|
||||
| `--branch=<name>` | Использовать другую ветку репозитория вместо `master` |
|
||||
| `--no-cache` | Очистить Go-кеш (`~/.cache/olcrtc`) перед сборкой - пересобрать с нуля |
|
||||
|
||||
`--no-cache` полезен когда нужно убедиться что собирается актуальный код (например после обновления зависимостей или при странных ошибках сборки). Без флага скрипт переиспользует кеш `gomod` и `gobuild`, что сильно ускоряет повторные запуски.
|
||||
Ключ должен совпадать на сервере и клиенте.
|
||||
|
||||
```sh
|
||||
./script/srv.sh --no-cache # сборка с нуля
|
||||
./script/srv.sh --branch=dev --no-cache # ветка dev, без кеша
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
### Auth (на каком сервисе передавать трафик)
|
||||
## Запустить сервер
|
||||
|
||||
```
|
||||
Выберите auth-провайдера:
|
||||
1) jitsi
|
||||
2) telemost
|
||||
3) wbstream
|
||||
Введите номер [1-3, по умолчанию: 1]:
|
||||
Создай `server.yaml`:
|
||||
|
||||
```yaml
|
||||
mode: srv
|
||||
auth:
|
||||
provider: jitsi
|
||||
room:
|
||||
id: "https://meet.small-dm.ru/myroom"
|
||||
crypto:
|
||||
key: "REPLACE_ME_WITH_64_HEX_CHARS"
|
||||
net:
|
||||
transport: datachannel
|
||||
dns: "8.8.8.8:53"
|
||||
data: data
|
||||
```
|
||||
|
||||
Выбери сервис. Полную матрицу совместимости смотри в [settings.md](settings.md).
|
||||
|
||||
**По умолчанию `jitsi`** - стабильно работает на datachannel против self-hosted и публичных Jitsi инстансов (например `meet.small-dm.ru`, `meet1.arbitr.ru` или `meet.handyweb.org`). Проверьте в браузере, какой из них доступен в вашей сети.
|
||||
|
||||
### Transport (как именно передавать данные)
|
||||
|
||||
```
|
||||
Выберите транспорт:
|
||||
1) datachannel
|
||||
2) videochannel
|
||||
3) seichannel
|
||||
4) vp8channel
|
||||
Введите номер [1-4, по умолчанию: 1]:
|
||||
```
|
||||
|
||||
Рекомендации:
|
||||
- **datachannel** - самый быстрый, минимальный пинг. Стабильно работает с `jitsi` через colibri-ws bridge channel. **WBStream DC не работает** в обычном guest flow (токены без `canPublishData`). **Telemost удалил DC**.
|
||||
- **vp8channel** - работает с telemost и wbstream, быстрый, но большой пинг.
|
||||
- **seichannel** - работает только с wbstream, медленный, но мелкий пинг.
|
||||
- **videochannel** - работает с wbstream стабильно, с telemost по возможности; самый медленный и с большим пингом.
|
||||
|
||||
**Рекомендуемая комбинация: `jitsi + datachannel`** - работает стабильно, не требует регистрации, легко поднимать на своём сервере. Альтернатива: `wbstream + vp8channel`.
|
||||
|
||||
### Room ID
|
||||
|
||||
```
|
||||
Введите Room ID:
|
||||
```
|
||||
|
||||
Для **jitsi** - полный URL комнаты в формате `https://host/room` (например `https://meet.small-dm.ru/myroom` или `https://meet1.arbitr.ru/myroom`). Имя комнаты придумывается на лету, без регистрации. Подойдёт любой публичный или self-hosted Jitsi Meet. **Обязательно проверьте, какой сервер работает в вашей сети** - откройте в браузере и используйте тот, который открывается.
|
||||
|
||||
Для **telemost** и **wbstream** - создай руму через сайт ([telemost](https://telemost.yandex.ru/), [wbstream](https://stream.wb.ru)) и вставь её ID.
|
||||
|
||||
### DNS
|
||||
|
||||
```
|
||||
DNS-сервер [по умолчанию: 8.8.8.8:53]:
|
||||
```
|
||||
|
||||
Нажми Enter. Менять не нужно если нет причин, на всякий можно поставить 77.88.8.8 или DNS твоего провайдера.
|
||||
|
||||
### SOCKS5 прокси для исходящего трафика
|
||||
|
||||
```
|
||||
Использовать SOCKS5-прокси для исходящего трафика? (y/N):
|
||||
```
|
||||
|
||||
Если нет - просто Enter, если надо то введи `y`. Нужно чтобы сервер сам ходил через прокси.
|
||||
|
||||
### Параметры транспорта (только для videochannel)
|
||||
|
||||
```
|
||||
Видео-кодек:
|
||||
1) qrcode
|
||||
2) tile (требует 1080x1080)
|
||||
Введите номер [1-2, по умолчанию: 1]:
|
||||
```
|
||||
|
||||
Выбери кодек:
|
||||
- **qrcode** - QR-коды, настраиваемое разрешение, стабильный, медленный.
|
||||
- **tile** - тайловый кодек, только 1080x1080, поддерживает Reed-Solomon коррекцию, не стабилен, более быстрый.
|
||||
|
||||
#### qrcode
|
||||
|
||||
```
|
||||
Ширина видео [по умолчанию: 1920]:
|
||||
Высота видео [по умолчанию: 1080]:
|
||||
Коррекция ошибок QR (low/medium/high/highest) [по умолчанию: low]:
|
||||
Размер QR-фрагмента в байтах [по умолчанию: 0 (авто)]:
|
||||
```
|
||||
|
||||
- **Ширина / высота видео** - разрешение видео. Больше = больше данных за кадр, но тяжелее поток.
|
||||
- **Коррекция ошибок QR** - `low` быстрее, `highest` надёжнее при плохом канале.
|
||||
- **Размер QR-фрагмента** - размер фрагмента в байтах. `0` = автоматически.
|
||||
|
||||
#### tile
|
||||
|
||||
```
|
||||
[*] Выбран tile-кодек, принудительно выставляю 1080x1080
|
||||
Размер tile-модуля в пикселях 1..270 [по умолчанию: 4]:
|
||||
Процент Reed-Solomon parity для tile 0..200 [по умолчанию: 20]:
|
||||
```
|
||||
|
||||
- **Размер tile-модуля** - размер одного тайла в пикселях. Меньше = больше данных за кадр.
|
||||
- **Tile Reed-Solomon parity** - процент избыточности. `0` = без коррекции, `20` оптимально.
|
||||
|
||||
#### Общие параметры (для обоих кодеков)
|
||||
|
||||
```
|
||||
FPS видео [по умолчанию: 30]:
|
||||
Битрейт видео [по умолчанию: 2M]:
|
||||
Аппаратное ускорение (none/nvenc) [по умолчанию: none]:
|
||||
```
|
||||
|
||||
- **FPS видео** - кадров в секунду. Больше FPS = выше пропускная способность, больше нагрузка на CPU.
|
||||
- **Битрейт видео** - битрейт ffmpeg. Примеры: `2M`, `5M`, `500K`.
|
||||
- **Аппаратное ускорение** - `none` если нет GPU, `nvenc` для NVIDIA GPU.
|
||||
|
||||
---
|
||||
|
||||
### Параметры транспорта (только для vp8channel)
|
||||
|
||||
```
|
||||
VP8 FPS [по умолчанию: 60]:
|
||||
VP8 batch size (кадров за тик) [по умолчанию: 64]:
|
||||
```
|
||||
|
||||
Нажми Enter, если устраивают значения по умолчанию `60` и `64`.
|
||||
|
||||
### Параметры транспорта (только для seichannel)
|
||||
|
||||
```
|
||||
SEI FPS [по умолчанию: 60]:
|
||||
SEI batch size (кадров за тик) [по умолчанию: 64]:
|
||||
Размер SEI-фрагмента в байтах [по умолчанию: 900]:
|
||||
SEI ACK timeout в миллисекундах [по умолчанию: 2000]:
|
||||
```
|
||||
|
||||
Нажми Enter для всех - значения по умолчанию оптимальны.
|
||||
|
||||
|
||||
|
||||
### Результат
|
||||
|
||||
После запуска скрипт выведет:
|
||||
|
||||
```
|
||||
[+] Сервер успешно запущен!
|
||||
|
||||
Имя контейнера: olcrtc-server
|
||||
Auth: wbstream
|
||||
Transport: datachannel
|
||||
Room ID: abc123xyz
|
||||
Ключ шифрования: d823fa01cb3e0609b67322f7cf984c4ee2e294936fc24ef38c9e59f4799
|
||||
```
|
||||
|
||||
**Сохрани Room ID и ключ шифрования** - они нужны для клиента.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 3: Запустить клиент
|
||||
|
||||
На своей машине (домашний ПК, ноутбук):
|
||||
Запусти:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/openlibrecommunity/olcrtc --recurse-submodules
|
||||
cd olcrtc
|
||||
./script/cnc.sh
|
||||
./build/olcrtc-linux-amd64 server.yaml
|
||||
```
|
||||
|
||||
Отвечай на те же вопросы что на сервере - **auth, transport и room ID должны совпадать**.
|
||||
## Запустить клиент
|
||||
|
||||
Когда спросит ключ:
|
||||
Создай `client.yaml` на клиентской машине. `auth.provider`, `room.id`, `crypto.key` и `net.transport` должны совпадать с сервером.
|
||||
|
||||
```
|
||||
Введите ключ шифрования (hex):
|
||||
```yaml
|
||||
mode: cnc
|
||||
auth:
|
||||
provider: jitsi
|
||||
room:
|
||||
id: "https://meet.small-dm.ru/myroom"
|
||||
crypto:
|
||||
key: "REPLACE_ME_WITH_64_HEX_CHARS"
|
||||
net:
|
||||
transport: datachannel
|
||||
dns: "8.8.8.8:53"
|
||||
socks:
|
||||
host: "127.0.0.1"
|
||||
port: 8808
|
||||
data: data
|
||||
```
|
||||
|
||||
Вставь ключ с сервера.
|
||||
Запусти:
|
||||
|
||||
### SOCKS5 адрес и порт
|
||||
|
||||
```
|
||||
SOCKS5 IP [по умолчанию: 127.0.0.1]:
|
||||
SOCKS5 порт [по умолчанию: 8808]:
|
||||
```sh
|
||||
./build/olcrtc-linux-amd64 client.yaml
|
||||
```
|
||||
|
||||
Нажми Enter оба раза. Прокси поднимется на `127.0.0.1:8808`.
|
||||
После запуска SOCKS5 будет слушать на `127.0.0.1:8808`.
|
||||
|
||||
### SOCKS5 аутентификация (необязательно)
|
||||
|
||||
```
|
||||
SOCKS5 логин (оставь пустым, чтобы отключить auth):
|
||||
```
|
||||
|
||||
Если нужна защита логином и паролем - введи логин, затем пароль. Если нет - просто Enter, аутентификация будет отключена.
|
||||
|
||||
### Результат
|
||||
|
||||
```
|
||||
[+] Клиент успешно запущен!
|
||||
|
||||
Имя контейнера: olcrtc-client
|
||||
SOCKS5 proxy: 127.0.0.1:8808
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Шаг 4: Проверить
|
||||
## Проверить
|
||||
|
||||
```sh
|
||||
curl --socks5-hostname 127.0.0.1:8808 https://icanhazip.com
|
||||
```
|
||||
|
||||
Должен вернуть IP твоего сервера.
|
||||
|
||||
Или выставить переменную окружения чтобы всё шло через прокси:
|
||||
|
||||
```sh
|
||||
export all_proxy=socks5h://127.0.0.1:8808
|
||||
curl https://icanhazip.com
|
||||
```
|
||||
|
||||
---
|
||||
Должен вернуться IP сервера.
|
||||
|
||||
## Управление
|
||||
|
||||
### Логи
|
||||
Остановка ручного запуска - `Ctrl+C`.
|
||||
|
||||
Если процесс запущен в фоне:
|
||||
|
||||
```sh
|
||||
podman ps --filter name=olcrtc
|
||||
podman logs -f olcrtc-server-xxxxxxxx # на сервере
|
||||
podman logs -f olcrtc-client-xxxxxxxx # на клиенте
|
||||
pgrep -af olcrtc
|
||||
kill <pid>
|
||||
```
|
||||
|
||||
### Остановить
|
||||
Обновление:
|
||||
|
||||
```sh
|
||||
podman ps --filter name=olcrtc
|
||||
podman stop olcrtc-server-xxxxxxxx
|
||||
podman stop olcrtc-client-xxxxxxxx
|
||||
```
|
||||
|
||||
### Перезапустить (просто запусти скрипт снова)
|
||||
|
||||
Скрипты создают новый контейнер с уникальным именем. Если нужно заменить старый инстанс, сначала останови его через `podman stop`, затем запусти скрипт заново.
|
||||
|
||||
---
|
||||
|
||||
## Обновить уже запущенный инстанс
|
||||
|
||||
Уже запущенный контейнер сам не обновляется: внутри него остаётся бинарник, который был собран на момент запуска. Чтобы перейти на актуальный код из репозитория, останови старый контейнер и запусти скрипт заново.
|
||||
|
||||
### 1. Обновить локальную копию репозитория
|
||||
|
||||
```sh
|
||||
cd olcrtc
|
||||
git pull --recurse-submodules
|
||||
mage build
|
||||
```
|
||||
|
||||
Это обновляет локальные скрипты `script/srv.sh` и `script/cnc.sh`. Сами скрипты при запуске всё равно клонируют актуальный `master` и собирают бинарник заново.
|
||||
Перезапусти сервер и клиент с теми же YAML-конфигами.
|
||||
|
||||
### 2. Остановить старый контейнер
|
||||
## Несколько инстансов
|
||||
|
||||
Посмотреть запущенные инстансы:
|
||||
Можно запустить несколько серверов или клиентов на одной машине: создай отдельный YAML для каждого инстанса. Для клиентов используй разные SOCKS5-порты:
|
||||
|
||||
```sh
|
||||
podman ps --filter name=olcrtc
|
||||
```yaml
|
||||
socks:
|
||||
host: "127.0.0.1"
|
||||
port: 8809
|
||||
```
|
||||
|
||||
Остановить нужный сервер или клиент:
|
||||
|
||||
```sh
|
||||
podman stop olcrtc-server-xxxxxxxx
|
||||
podman stop olcrtc-client-xxxxxxxx
|
||||
```
|
||||
|
||||
Если нужно остановить все olcrtc-контейнеры на машине:
|
||||
|
||||
```sh
|
||||
podman stop $(podman ps -q --filter name=olcrtc)
|
||||
```
|
||||
|
||||
### 3. Запустить заново
|
||||
|
||||
Сервер:
|
||||
|
||||
```sh
|
||||
./script/srv.sh --no-cache
|
||||
```
|
||||
|
||||
Клиент:
|
||||
|
||||
```sh
|
||||
./script/cnc.sh --no-cache
|
||||
```
|
||||
|
||||
`--no-cache` не обязателен, но полезен после обновления: Go-модули и build-cache будут очищены, и бинарник точно соберётся с нуля. При повторном запуске укажи те же `auth`, `transport`, `room ID` и ключ, что были у старого инстанса. Серверный ключ хранится в `~/.olcrtc_key`, поэтому `srv.sh` переиспользует его автоматически.
|
||||
|
||||
---
|
||||
|
||||
## Несколько инстансов на одном сервере
|
||||
|
||||
Можно запустить несколько серверов olcrtc на одной машине с разными конфигами (разные провайдеры, комнаты, транспорты). Просто запусти `srv.sh` повторно - каждый запуск создаёт контейнер с уникальным именем (`olcrtc-server-<random>`), они не конфликтуют между собой.
|
||||
|
||||
```sh
|
||||
./script/srv.sh # первый инстанс - например jitsi + datachannel
|
||||
./script/srv.sh # второй инстанс - например wbstream + vp8channel
|
||||
./script/srv.sh # третий - другая комната, другой провайдер, и т.д.
|
||||
```
|
||||
|
||||
Каждый запуск спросит свои параметры (auth, transport, room ID) и выдаст свой ключ шифрования. На клиенте для каждого инстанса запускай отдельный `cnc.sh` с **разными SOCKS5 портами** - чтобы переключаться между ними в olcbox.
|
||||
|
||||
```sh
|
||||
./script/cnc.sh # первый клиент - порт 8808 (по умолчанию)
|
||||
./script/cnc.sh # второй клиент - укажи порт 8809
|
||||
./script/cnc.sh # третий - порт 8810, и т.д.
|
||||
```
|
||||
|
||||
Посмотреть все запущенные инстансы:
|
||||
|
||||
```sh
|
||||
podman ps --filter name=olcrtc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Хочешь собрать руками без Podman? -> [Мануальная сборка](manual.md)
|
||||
|
||||
Все настройки и матрица совместимости -> [settings.md](settings.md)
|
||||
Все настройки и матрица совместимости: [settings.md](settings.md). Подробная ручная сборка: [manual.md](manual.md).
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
> **Важно:** Обязательно проверяйте, есть ли сервис видеозвонков у вас в белых списках. Если его там нет - используйте другой. Список всех сервисов в белых списках скоро будет опубликован.
|
||||
|
||||
|
||||
Этот способ для тех кто хочет собрать бинарник руками без Docker/Podman.
|
||||
Этот способ для тех кто хочет собрать нативный бинарник руками.
|
||||
Нужен Go 1.26+, mage, git.
|
||||
|
||||
---
|
||||
@@ -428,8 +428,6 @@ sudo systemctl restart olcrtc-client
|
||||
mage build # собрать для текущей платформы
|
||||
mage cross # собрать для всех платформ
|
||||
mage mobile # собрать Android AAR
|
||||
mage docker # собрать образ через docker
|
||||
mage podman # собрать образ через podman
|
||||
mage clean # удалить build/
|
||||
```
|
||||
|
||||
@@ -482,7 +480,6 @@ SOAK_CARRIERS=jitsi SOAK_DURATION=30m mage soak
|
||||
- `E2E_CARRIERS`, `E2E_TRANSPORTS`, `E2E_TIMEOUT`, `E2E_STRESS`, `E2E_STRESS_DURATION`
|
||||
- `STRESS_BULK_DURATION`, `STRESS_ECHO_DURATION`, `STRESS_CASE_TIMEOUT`, `STRESS_TIMEOUT`
|
||||
- `SOAK_CARRIERS`, `SOAK_TRANSPORTS`, `SOAK_DURATION`, `SOAK_CHAOS`
|
||||
- `DOCKER_TAG`
|
||||
|
||||
---
|
||||
|
||||
@@ -578,6 +575,6 @@ data: data
|
||||
|
||||
---
|
||||
|
||||
Используешь скрипты вместо ручной сборки? -> [Быстрый старт](fast.md)
|
||||
Нужен короткий путь без подробностей? -> [Быстрый старт](fast.md)
|
||||
|
||||
Все настройки и матрица совместимости -> [settings.md](settings.md)
|
||||
|
||||
@@ -145,22 +145,22 @@ transport. Используй одинаковые traffic-настройки н
|
||||
|
||||
## vp8channel
|
||||
|
||||
**Рекомендуется: `fps: 60`, `batch_size: 64`** (числа лучше чётные, больший batch = выше скорость)
|
||||
**Рекомендуется: `fps: 30`, `batch_size: 64`** (меньше FPS снижает CPU-нагрузку, больший batch = выше скорость)
|
||||
|
||||
| YAML поле | Описание | По умолчанию |
|
||||
|-----------|----------|:------------:|
|
||||
| `vp8.fps` | FPS VP8 потока | `60` |
|
||||
| `vp8.fps` | FPS VP8 потока | `30` |
|
||||
| `vp8.batch_size` | Кадров за тик | `64` |
|
||||
|
||||
---
|
||||
|
||||
## seichannel
|
||||
|
||||
**Рекомендуется: `fps: 60`, `batch_size: 64`, `fragment_size: 900`, `ack_timeout_ms: 2000`**
|
||||
**Рекомендуется: `fps: 30`, `batch_size: 64`, `fragment_size: 900`, `ack_timeout_ms: 2000`**
|
||||
|
||||
| YAML поле | Описание | По умолчанию |
|
||||
|-----------|----------|:------------:|
|
||||
| `sei.fps` | FPS H264 потока | `60` |
|
||||
| `sei.fps` | FPS H264 потока | `30` |
|
||||
| `sei.batch_size` | Кадров за тик | `64` |
|
||||
| `sei.fragment_size` | Размер фрагмента в байтах | `900` |
|
||||
| `sei.ack_timeout_ms` | Таймаут ACK в миллисекундах | `2000` |
|
||||
@@ -169,7 +169,7 @@ transport. Используй одинаковые traffic-настройки н
|
||||
|
||||
## videochannel
|
||||
|
||||
**Рекомендуется: `codec: qrcode`, `width: 1080`, `height: 1080`, `fps: 60`, `bitrate: "5000k"`, `hw: none`**
|
||||
**Рекомендуется: `codec: qrcode`, `width: 1080`, `height: 1080`, `fps: 30`, `bitrate: "5000k"`, `hw: none`**
|
||||
|
||||
| YAML поле | Описание | По умолчанию |
|
||||
|-----------|----------|:------------:|
|
||||
@@ -276,7 +276,7 @@ net:
|
||||
transport: vp8channel
|
||||
dns: "8.8.8.8:53"
|
||||
vp8:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
data: data
|
||||
```
|
||||
@@ -297,7 +297,7 @@ socks:
|
||||
host: "127.0.0.1"
|
||||
port: 8808
|
||||
vp8:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
data: data
|
||||
```
|
||||
@@ -319,7 +319,7 @@ net:
|
||||
transport: seichannel
|
||||
dns: "8.8.8.8:53"
|
||||
sei:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
fragment_size: 900
|
||||
ack_timeout_ms: 2000
|
||||
@@ -342,7 +342,7 @@ socks:
|
||||
host: "127.0.0.1"
|
||||
port: 8808
|
||||
sei:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
fragment_size: 900
|
||||
ack_timeout_ms: 2000
|
||||
@@ -367,7 +367,7 @@ video:
|
||||
codec: qrcode
|
||||
width: 1080
|
||||
height: 1080
|
||||
fps: 60
|
||||
fps: 30
|
||||
bitrate: "5000k"
|
||||
hw: none
|
||||
data: data
|
||||
@@ -392,7 +392,7 @@ video:
|
||||
codec: qrcode
|
||||
width: 1080
|
||||
height: 1080
|
||||
fps: 60
|
||||
fps: 30
|
||||
bitrate: "5000k"
|
||||
hw: none
|
||||
data: data
|
||||
|
||||
@@ -155,7 +155,7 @@ crypto:
|
||||
net:
|
||||
transport: vp8channel
|
||||
vp8:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
data: data
|
||||
```
|
||||
@@ -179,7 +179,7 @@ crypto:
|
||||
net:
|
||||
transport: seichannel
|
||||
sei:
|
||||
fps: 60
|
||||
fps: 30
|
||||
batch_size: 64
|
||||
fragment_size: 900
|
||||
ack_timeout_ms: 2000
|
||||
@@ -207,7 +207,7 @@ net:
|
||||
video:
|
||||
width: 1080
|
||||
height: 1080
|
||||
fps: 60
|
||||
fps: 30
|
||||
bitrate: "5000k"
|
||||
hw: none
|
||||
codec: qrcode
|
||||
|
||||
@@ -44,9 +44,9 @@ const (
|
||||
defaultVideoBitrate = "2M"
|
||||
defaultVideoHW = "none"
|
||||
defaultVideoQRRecovery = "low"
|
||||
defaultVP8FPS = 60
|
||||
defaultVP8FPS = 30
|
||||
defaultVP8BatchSize = 64
|
||||
defaultSEIFPS = 60
|
||||
defaultSEIFPS = 30
|
||||
defaultSEIBatchSize = 64
|
||||
defaultSEIFragmentSize = 900
|
||||
defaultSEIAckTimeoutMS = 2000
|
||||
|
||||
@@ -22,14 +22,14 @@ func TestApplyTransportDefaults(t *testing.T) {
|
||||
{
|
||||
name: "vp8",
|
||||
in: Config{Transport: transportVP8},
|
||||
want: Config{Transport: transportVP8, VP8: VP8Config{FPS: 60, BatchSize: 64}},
|
||||
want: Config{Transport: transportVP8, VP8: VP8Config{FPS: 30, BatchSize: 64}},
|
||||
},
|
||||
{
|
||||
name: "sei",
|
||||
in: Config{Transport: transportSEI},
|
||||
want: Config{
|
||||
Transport: transportSEI,
|
||||
SEI: SEIConfig{FPS: 60, BatchSize: 64, FragmentSize: 900, AckTimeoutMS: 2000},
|
||||
SEI: SEIConfig{FPS: 30, BatchSize: 64, FragmentSize: 900, AckTimeoutMS: 2000},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -48,7 +48,8 @@ func TestSetupCipherRejectsBadInput(t *testing.T) {
|
||||
|
||||
func TestSmuxConfig(t *testing.T) {
|
||||
cfg := smuxConfig(0)
|
||||
if cfg.Version != 2 || cfg.KeepAliveDisabled || cfg.MaxFrameSize != 32768 || cfg.MaxReceiveBuffer != 16*1024*1024 {
|
||||
if cfg.Version != 2 || cfg.KeepAliveDisabled || cfg.MaxFrameSize != 32768 ||
|
||||
cfg.MaxReceiveBuffer != 8*1024*1024 || cfg.MaxStreamBuffer != 512*1024 {
|
||||
t.Fatalf("smuxConfig(0) = %+v", cfg)
|
||||
}
|
||||
capped := smuxConfig(4096)
|
||||
|
||||
@@ -920,7 +920,7 @@ func validSessionConfig(mode, carrierName, transportName string) session.Config
|
||||
Width: 1080, Height: 1080, FPS: 30, Bitrate: "1M",
|
||||
HW: videoHWNone, Codec: "tile", TileModule: 4, TileRS: 20,
|
||||
},
|
||||
VP8: session.VP8Config{FPS: 60, BatchSize: 64},
|
||||
VP8: session.VP8Config{FPS: 30, BatchSize: 64},
|
||||
SEI: session.SEIConfig{FPS: 30, BatchSize: 4, FragmentSize: 512, AckTimeoutMS: 1500},
|
||||
}
|
||||
}
|
||||
@@ -935,7 +935,7 @@ func e2eTransportOptions(transportName string) transport.Options {
|
||||
return videochannel.Options{
|
||||
Width: 1080,
|
||||
Height: 1080,
|
||||
FPS: 60,
|
||||
FPS: 30,
|
||||
Bitrate: "5000k",
|
||||
HW: videoHWNone,
|
||||
QRSize: 512,
|
||||
@@ -945,9 +945,9 @@ func e2eTransportOptions(transportName string) transport.Options {
|
||||
TileRS: 20,
|
||||
}
|
||||
case "vp8channel":
|
||||
return vp8channel.Options{FPS: 60, BatchSize: 64}
|
||||
return vp8channel.Options{FPS: 30, BatchSize: 64}
|
||||
case "seichannel":
|
||||
return seichannel.Options{FPS: 60, BatchSize: 64, FragmentSize: 512, AckTimeoutMS: 1500}
|
||||
return seichannel.Options{FPS: 30, BatchSize: 64, FragmentSize: 512, AckTimeoutMS: 1500}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -736,7 +736,7 @@ func (s *Session) bridgeKeepalive() {
|
||||
// transport (WebSocket or BOSH) keeps observing application traffic.
|
||||
//
|
||||
// Why we need it: Prosody's BOSH plugin defaults to bosh_max_inactivity=60s
|
||||
// (and Jitsi's docker images set it explicitly to 60s on visitor domains).
|
||||
// (and some Jitsi deployments set it explicitly to 60s on visitor domains).
|
||||
// Once the inactivity timer expires Prosody returns <body type="terminate"/>
|
||||
// and our long-poll fails with "connection closed" — exactly the symptom
|
||||
// observed when nobody else joins the room within 60s. A 25s ping cadence
|
||||
|
||||
@@ -36,11 +36,11 @@ var ErrClosed = errors.New("muxconn: closed")
|
||||
const (
|
||||
// inboundQueue is the buffered capacity of the Push -> Read pipeline.
|
||||
// It absorbs short Read stalls without applying back-pressure to the
|
||||
// transport callback. Frames are typically smux-sized (well under
|
||||
// 16 KiB), so 256 amounts to a few MiB of in-flight data, which is
|
||||
// enough for sustained throughput on every transport we have without
|
||||
// unbounded growth on a stuck reader.
|
||||
inboundQueue = 256
|
||||
// transport callback. Frames are typically smux-sized (up to 32 KiB),
|
||||
// so 128 amounts to a few MiB of in-flight data, which is
|
||||
// enough for sustained throughput without letting a stuck reader retain
|
||||
// a large pool-backed working set per connection.
|
||||
inboundQueue = 128
|
||||
|
||||
// pooledFrameCap is the capacity each pooled plaintext buffer is born
|
||||
// with. It is sized to fit the largest smux frame any of our
|
||||
@@ -246,7 +246,7 @@ func (c *Conn) Write(p []byte) (int, error) {
|
||||
// latency to interactive request/response traffic. Fall back to a
|
||||
// modest sleep only if the link is truly congested.
|
||||
const (
|
||||
fastSpinAttempts = 200
|
||||
fastSpinAttempts = 16
|
||||
slowPollDelay = 2 * time.Millisecond
|
||||
)
|
||||
for attempt := 0; ; attempt++ {
|
||||
|
||||
@@ -28,6 +28,10 @@ const (
|
||||
// MinSmuxWirePayload is the smallest useful encrypted transport payload
|
||||
// cap that can still carry a non-empty smux frame.
|
||||
MinSmuxWirePayload = SmuxWireOverhead + 1
|
||||
|
||||
smuxMaxFrameSize = 32 * 1024
|
||||
smuxMaxReceiveBuffer = 8 * 1024 * 1024
|
||||
smuxMaxStreamBuffer = 512 * 1024
|
||||
)
|
||||
|
||||
// ErrKeyRequired is returned when no encryption key is provided.
|
||||
@@ -63,15 +67,15 @@ func SmuxConfig(maxWirePayload int) *smux.Config {
|
||||
cfg := smux.DefaultConfig()
|
||||
cfg.Version = 2
|
||||
cfg.KeepAliveDisabled = false
|
||||
cfg.MaxFrameSize = 32768
|
||||
cfg.MaxFrameSize = smuxMaxFrameSize
|
||||
if maxWirePayload >= MinSmuxWirePayload {
|
||||
maxFrameSize := maxWirePayload - SmuxWireOverhead
|
||||
if maxFrameSize < cfg.MaxFrameSize {
|
||||
cfg.MaxFrameSize = maxFrameSize
|
||||
}
|
||||
}
|
||||
cfg.MaxReceiveBuffer = 16 * 1024 * 1024
|
||||
cfg.MaxStreamBuffer = 1024 * 1024
|
||||
cfg.MaxReceiveBuffer = smuxMaxReceiveBuffer
|
||||
cfg.MaxStreamBuffer = smuxMaxStreamBuffer
|
||||
cfg.KeepAliveInterval = 10 * time.Second
|
||||
cfg.KeepAliveTimeout = 30 * time.Second
|
||||
return cfg
|
||||
|
||||
@@ -37,6 +37,9 @@ func TestSmuxConfigDefault(t *testing.T) {
|
||||
if cfg.Version != 2 || cfg.MaxFrameSize != 32768 {
|
||||
t.Fatalf("SmuxConfig(0) = %+v", cfg)
|
||||
}
|
||||
if cfg.MaxReceiveBuffer != 8*1024*1024 || cfg.MaxStreamBuffer != 512*1024 {
|
||||
t.Fatalf("SmuxConfig(0) buffers = %+v", cfg)
|
||||
}
|
||||
if cfg.KeepAliveDisabled || cfg.KeepAliveInterval != 10*time.Second ||
|
||||
cfg.KeepAliveTimeout != 30*time.Second {
|
||||
t.Fatalf("SmuxConfig(0) keepalive = %+v", cfg)
|
||||
|
||||
@@ -49,7 +49,8 @@ func TestSetupCipherRejectsBadInput(t *testing.T) {
|
||||
|
||||
func TestSmuxConfig(t *testing.T) {
|
||||
cfg := smuxConfig(0)
|
||||
if cfg.Version != 2 || cfg.KeepAliveDisabled || cfg.MaxFrameSize != 32768 || cfg.MaxReceiveBuffer != 16*1024*1024 {
|
||||
if cfg.Version != 2 || cfg.KeepAliveDisabled || cfg.MaxFrameSize != 32768 ||
|
||||
cfg.MaxReceiveBuffer != 8*1024*1024 || cfg.MaxStreamBuffer != 512*1024 {
|
||||
t.Fatalf("smuxConfig(0) = %+v", cfg)
|
||||
}
|
||||
capped := smuxConfig(4096)
|
||||
|
||||
@@ -26,7 +26,7 @@ const (
|
||||
defaultFragmentSize = 900
|
||||
defaultAckTimeout = 3 * time.Second
|
||||
defaultFrameInterval = 16 * time.Millisecond
|
||||
defaultFPS = 60
|
||||
defaultFPS = 30
|
||||
defaultBatchSize = 64
|
||||
defaultConnectTimeout = 30 * time.Second
|
||||
maxSendAttempts = 4
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultFPS = 60
|
||||
defaultFPS = 30
|
||||
defaultBatchSize = 64
|
||||
// defaultMaxBytesPerSec paces the wire byte-rate just under the Telemost
|
||||
// SFU's measured per-slot policer knee (~1.4 MiB/s). Above it the SFU
|
||||
|
||||
@@ -32,13 +32,13 @@ import (
|
||||
const (
|
||||
defaultMaxPayloadSize = 60 * 1024
|
||||
defaultConnectTimeout = 60 * time.Second
|
||||
rtpBufSize = 65536
|
||||
rtpBufSize = 65536
|
||||
// outboundQueueSize bounds KCP packets waiting for the paced writer. Sized
|
||||
// to a couple of send windows so KCP's flush never blocks (a blocked
|
||||
// WriteTo would stall KCP's update loop and delay ACKs); the paced writer
|
||||
// keeps it drained so this depth is headroom, not standing latency.
|
||||
outboundQueueSize = 2048
|
||||
inboundQueueSize = 8192
|
||||
outboundQueueSize = 1536
|
||||
inboundQueueSize = 4096
|
||||
canSendHighWatermark = 90 // percent
|
||||
keepaliveIdlePeriod = 100 * time.Millisecond
|
||||
)
|
||||
|
||||
16
magefile.go
16
magefile.go
@@ -147,22 +147,6 @@ func Mobile() error {
|
||||
)
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Container
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// Docker builds the image using docker.
|
||||
func Docker() error {
|
||||
tag := envOr("DOCKER_TAG", "olcrtc:latest")
|
||||
return sh.RunV("docker", "build", "-t", tag, ".")
|
||||
}
|
||||
|
||||
// Podman builds the image using podman.
|
||||
func Podman() error {
|
||||
tag := envOr("DOCKER_TAG", "olcrtc:latest")
|
||||
return sh.RunV("podman", "build", "-t", tag, ".")
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Quality
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -708,7 +708,7 @@ func ensureDefaultConfigLocked() {
|
||||
transport: defaultTransport,
|
||||
dnsServer: defaultDNSServer,
|
||||
socksListenHost: defaultSocksHost,
|
||||
vp8FPS: 60,
|
||||
vp8FPS: 30,
|
||||
vp8BatchSize: 8,
|
||||
livenessInterval: control.DefaultInterval,
|
||||
livenessTimeout: control.DefaultTimeout,
|
||||
|
||||
@@ -177,7 +177,7 @@ func TestStartWithInjectedRunnerLifecycle(t *testing.T) {
|
||||
opts, _ := cfg.TransportOptions.(vp8channel.Options)
|
||||
if cfg.Transport != dataTransport || cfg.Carrier != "jitsi" ||
|
||||
cfg.RoomURL != testRoomID || cfg.DeviceID != "client" || cfg.LocalAddr != "0.0.0.0:1080" ||
|
||||
cfg.DNSServer != defaultDNSServer || opts.FPS != 60 || opts.BatchSize != 8 ||
|
||||
cfg.DNSServer != defaultDNSServer || opts.FPS != 30 || opts.BatchSize != 8 ||
|
||||
cfg.Liveness.Interval != 2500*time.Millisecond ||
|
||||
cfg.Liveness.Timeout != 750*time.Millisecond ||
|
||||
cfg.Liveness.Failures != 4 {
|
||||
|
||||
@@ -39,8 +39,6 @@ Community ui client: [alananisimov/olcbox](https://github.com/alananisimov/olcbo
|
||||
|
||||
[More info](docs/about.md)
|
||||
|
||||
[Docker setup](docs/docker.md)
|
||||
|
||||
[Client URI format](docs/uri.md)
|
||||
|
||||
[Client subscription format](docs/sub.md)
|
||||
@@ -53,7 +51,7 @@ Encrypted TCP-over-WebRTC tunnel. Traffic is disguised as a regular video call o
|
||||
|
||||
**Transports:** `datachannel` - `vp8channel` - `seichannel` - `videochannel`
|
||||
|
||||
**Platforms:** Linux, macOS, Windows, Android (gomobile), Docker, embeddable Go library
|
||||
**Platforms:** Linux, macOS, Windows, Android (gomobile), embeddable Go library
|
||||
|
||||
```
|
||||
app -> SOCKS5 -> olcrtc cnc -> WebRTC/SFU service -> olcrtc srv -> internet
|
||||
|
||||
465
script/cnc.sh
465
script/cnc.sh
@@ -1,465 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "ЕСЛИ У ВАС ЕСТЬ ПРОБЛЕМЫ - Я В КУРСЕ, ПРОЕКТ В БЕТЕ, ПО ПРОБЛЕМАМ В ЧАТ t.me/openlibrecommunity ИЛИ ВООБЩЕ НЕКУДА, ЖДИТЕ РЕЛИЗА"
|
||||
|
||||
|
||||
set -e
|
||||
|
||||
PODMAN_ID=$(tr -dc 'a-z0-9' </dev/urandom | head -c 8)
|
||||
CONTAINER_NAME="olcrtc-client-$PODMAN_ID"
|
||||
IMAGE_NAME="docker.io/library/golang:1.26-alpine3.22"
|
||||
REPO_URL="https://github.com/openlibrecommunity/olcrtc.git"
|
||||
WORK_DIR="/tmp/olcrtc-client-$PODMAN_ID"
|
||||
|
||||
SOCKS_IP="127.0.0.1"
|
||||
SOCKS_PORT="8808"
|
||||
BRANCH="master"
|
||||
NO_CACHE=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--branch=*)
|
||||
BRANCH="${1#*=}"
|
||||
shift
|
||||
;;
|
||||
--no-cache)
|
||||
NO_CACHE=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "=== OlcRTC Client Deployment Script ==="
|
||||
echo ""
|
||||
echo "[*] Using branch: $BRANCH"
|
||||
echo ""
|
||||
|
||||
if ! command -v podman &> /dev/null; then
|
||||
echo "[!] Installing Podman..."
|
||||
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
SUDO=""
|
||||
elif command -v sudo &> /dev/null; then
|
||||
SUDO="sudo"
|
||||
elif command -v doas &> /dev/null; then
|
||||
SUDO="doas"
|
||||
else
|
||||
echo "[X] No sudo/doas found and not running as root. Cannot install podman."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if command -v apt &> /dev/null; then
|
||||
echo "[*] Detected apt (Debian/Ubuntu)"
|
||||
$SUDO apt update
|
||||
$SUDO apt install -y podman
|
||||
elif command -v dnf &> /dev/null; then
|
||||
echo "[*] Detected dnf (Fedora/RHEL)"
|
||||
$SUDO dnf install -y podman
|
||||
elif command -v yum &> /dev/null; then
|
||||
echo "[*] Detected yum (CentOS/RHEL)"
|
||||
$SUDO yum install -y podman
|
||||
elif command -v pacman &> /dev/null; then
|
||||
echo "[*] Detected pacman (Arch)"
|
||||
$SUDO pacman -Sy --noconfirm podman
|
||||
else
|
||||
echo "[X] Unsupported package manager. Install podman manually."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "[+] Using Podman"
|
||||
echo ""
|
||||
|
||||
validate_key() {
|
||||
case "$1" in
|
||||
*[!0-9a-fA-F]*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
[ "${#1}" -eq 64 ]
|
||||
}
|
||||
|
||||
echo "Select auth provider:"
|
||||
echo " 1) jitsi"
|
||||
echo " 2) telemost"
|
||||
echo " 3) wbstream"
|
||||
read -p "Enter choice [1-3, default: 1]: " AUTH_CHOICE
|
||||
|
||||
case "$AUTH_CHOICE" in
|
||||
2)
|
||||
AUTH="telemost"
|
||||
;;
|
||||
3)
|
||||
AUTH="wbstream"
|
||||
;;
|
||||
*)
|
||||
AUTH="jitsi"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "[*] Using auth: $AUTH"
|
||||
echo ""
|
||||
|
||||
echo "Select transport:"
|
||||
echo " 1) datachannel"
|
||||
echo " 2) videochannel"
|
||||
echo " 3) seichannel"
|
||||
echo " 4) vp8channel"
|
||||
read -p "Enter choice [1-4, default: 1]: " TRANSPORT_CHOICE
|
||||
|
||||
case "$TRANSPORT_CHOICE" in
|
||||
2)
|
||||
TRANSPORT="videochannel"
|
||||
;;
|
||||
3)
|
||||
TRANSPORT="seichannel"
|
||||
;;
|
||||
4)
|
||||
TRANSPORT="vp8channel"
|
||||
;;
|
||||
*)
|
||||
TRANSPORT="datachannel"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "[*] Using transport: $TRANSPORT"
|
||||
echo ""
|
||||
|
||||
if [ "$AUTH" = "jitsi" ]; then
|
||||
echo ""
|
||||
echo "Выберите Jitsi-сервер (проверьте в браузере, какой работает в вашей сети):"
|
||||
echo " 1) https://meet.small-dm.ru/"
|
||||
echo " 2) https://meet1.arbitr.ru/"
|
||||
echo " 3) https://meet.handyweb.org/"
|
||||
echo " 4) Другой (ввести вручную)"
|
||||
read -p "Введите номер [1-4, по умолчанию: 1]: " JITSI_SERVER_CHOICE
|
||||
|
||||
case "$JITSI_SERVER_CHOICE" in
|
||||
2)
|
||||
JITSI_BASE_URL="https://meet1.arbitr.ru"
|
||||
;;
|
||||
3)
|
||||
JITSI_BASE_URL="https://meet.handyweb.org"
|
||||
;;
|
||||
4)
|
||||
read -p "Введите URL Jitsi-сервера: " JITSI_BASE_INPUT
|
||||
JITSI_BASE_URL="${JITSI_BASE_INPUT%/}"
|
||||
if [ -z "$JITSI_BASE_URL" ]; then
|
||||
echo "[X] URL не может быть пустым"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
JITSI_BASE_URL="https://meet.small-dm.ru"
|
||||
;;
|
||||
esac
|
||||
|
||||
read -p "Enter Jitsi room name or URL: " JITSI_ROOM_INPUT
|
||||
if [ -z "$JITSI_ROOM_INPUT" ]; then
|
||||
echo "[X] Jitsi room name/URL cannot be empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$JITSI_ROOM_INPUT" in
|
||||
http://*|https://*|*/*)
|
||||
ROOM_ID="$JITSI_ROOM_INPUT"
|
||||
;;
|
||||
*)
|
||||
ROOM_ID="$JITSI_BASE_URL/$JITSI_ROOM_INPUT"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
read -p "Enter Room ID: " ROOM_ID
|
||||
fi
|
||||
|
||||
if [ -z "$ROOM_ID" ]; then
|
||||
echo "[X] Room ID/URL cannot be empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
read -p "Enter Encryption Key (hex): " KEY
|
||||
|
||||
if [ -z "$KEY" ]; then
|
||||
echo "[X] Encryption key cannot be empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! validate_key "$KEY"; then
|
||||
echo "[X] Encryption key must be 64 hex characters"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
read -p "DNS server [default: 8.8.8.8:53]: " DNS_INPUT
|
||||
DNS=${DNS_INPUT:-8.8.8.8:53}
|
||||
|
||||
echo ""
|
||||
read -p "SOCKS5 ip [default: 127.0.0.1]: " IP_INPUT
|
||||
SOCKS_IP=${IP_INPUT:-127.0.0.1}
|
||||
|
||||
echo ""
|
||||
read -p "SOCKS5 port [default: 8808]: " PORT_INPUT
|
||||
SOCKS_PORT=${PORT_INPUT:-8808}
|
||||
|
||||
echo ""
|
||||
read -p "SOCKS5 username (leave empty to disable auth): " SOCKS_USER_INPUT
|
||||
SOCKS_USER=${SOCKS_USER_INPUT:-}
|
||||
|
||||
SOCKS_PASS=""
|
||||
if [ -n "$SOCKS_USER" ]; then
|
||||
read -s -p "SOCKS5 password: " SOCKS_PASS_INPUT
|
||||
echo ""
|
||||
SOCKS_PASS=${SOCKS_PASS_INPUT:-}
|
||||
fi
|
||||
|
||||
case "$SOCKS_IP" in
|
||||
127.*|localhost|::1|\[::1\])
|
||||
;;
|
||||
*)
|
||||
if [ -z "$SOCKS_USER" ] || [ -z "$SOCKS_PASS" ]; then
|
||||
echo "[X] SOCKS auth required when binding outside loopback (set username and password)"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Transport-specific settings
|
||||
VIDEO_W=1920; VIDEO_H=1080; VIDEO_FPS=30; VIDEO_BITRATE="2M"; VIDEO_HW="none"
|
||||
VIDEO_CODEC="qrcode"; VIDEO_QR_SIZE=0; VIDEO_QR_RECOVERY="low"
|
||||
VIDEO_TILE_MODULE=4; VIDEO_TILE_RS=20
|
||||
VP8_FPS=25; VP8_BATCH=1
|
||||
SEI_FPS=60; SEI_BATCH=64; SEI_FRAG=900; SEI_ACK=2000
|
||||
|
||||
if [ "$TRANSPORT" = "videochannel" ]; then
|
||||
echo ""
|
||||
echo "--- Videochannel settings ---"
|
||||
|
||||
echo ""
|
||||
echo "Video codec:"
|
||||
echo " 1) qrcode"
|
||||
echo " 2) tile (requires 1080x1080)"
|
||||
read -p "Enter choice [1-2, default: 1]: " VCODEC_CHOICE
|
||||
|
||||
case "$VCODEC_CHOICE" in
|
||||
2)
|
||||
VIDEO_CODEC="tile"
|
||||
VIDEO_W=1080
|
||||
VIDEO_H=1080
|
||||
echo "[*] Tile codec selected - forcing 1080x1080"
|
||||
|
||||
read -p "Tile module size in pixels 1..270 [default: 4]: " VTILE_MOD_INPUT
|
||||
VIDEO_TILE_MODULE=${VTILE_MOD_INPUT:-4}
|
||||
|
||||
read -p "Tile Reed-Solomon parity percent 0..200 [default: 20]: " VTILE_RS_INPUT
|
||||
VIDEO_TILE_RS=${VTILE_RS_INPUT:-20}
|
||||
;;
|
||||
*)
|
||||
VIDEO_CODEC="qrcode"
|
||||
|
||||
read -p "Video width [default: 1920]: " VW_INPUT
|
||||
VIDEO_W=${VW_INPUT:-1920}
|
||||
|
||||
read -p "Video height [default: 1080]: " VH_INPUT
|
||||
VIDEO_H=${VH_INPUT:-1080}
|
||||
|
||||
read -p "QR error correction (low/medium/high/highest) [default: low]: " VQREC_INPUT
|
||||
VIDEO_QR_RECOVERY=${VQREC_INPUT:-low}
|
||||
|
||||
read -p "QR fragment size bytes [default: 0 (auto)]: " VQRSZ_INPUT
|
||||
VIDEO_QR_SIZE=${VQRSZ_INPUT:-0}
|
||||
;;
|
||||
esac
|
||||
|
||||
read -p "Video FPS [default: 30]: " VFPS_INPUT
|
||||
VIDEO_FPS=${VFPS_INPUT:-30}
|
||||
|
||||
read -p "Video bitrate [default: 2M]: " VBRT_INPUT
|
||||
VIDEO_BITRATE=${VBRT_INPUT:-2M}
|
||||
|
||||
read -p "Hardware acceleration (none/nvenc) [default: none]: " VHW_INPUT
|
||||
VIDEO_HW=${VHW_INPUT:-none}
|
||||
fi
|
||||
|
||||
if [ "$TRANSPORT" = "vp8channel" ]; then
|
||||
echo ""
|
||||
echo "--- VP8channel settings ---"
|
||||
|
||||
read -p "VP8 FPS [default: 25]: " VP8FPS_INPUT
|
||||
VP8_FPS=${VP8FPS_INPUT:-25}
|
||||
|
||||
read -p "VP8 batch size (frames per tick) [default: 1]: " VP8BATCH_INPUT
|
||||
VP8_BATCH=${VP8BATCH_INPUT:-1}
|
||||
fi
|
||||
|
||||
if [ "$TRANSPORT" = "seichannel" ]; then
|
||||
echo ""
|
||||
echo "--- SEIchannel settings ---"
|
||||
|
||||
read -p "SEI FPS [default: 60]: " SEIFPS_INPUT
|
||||
SEI_FPS=${SEIFPS_INPUT:-60}
|
||||
|
||||
read -p "SEI batch size (frames per tick) [default: 64]: " SEIBATCH_INPUT
|
||||
SEI_BATCH=${SEIBATCH_INPUT:-64}
|
||||
|
||||
read -p "SEI fragment size in bytes [default: 900]: " SEIFRAG_INPUT
|
||||
SEI_FRAG=${SEIFRAG_INPUT:-900}
|
||||
|
||||
read -p "SEI ACK timeout in milliseconds [default: 2000]: " SEIACK_INPUT
|
||||
SEI_ACK=${SEIACK_INPUT:-2000}
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "[*] Cleaning workspace..."
|
||||
rm -rf "$WORK_DIR"
|
||||
mkdir -p "$WORK_DIR"
|
||||
|
||||
CACHE_DIR="${OLCRTC_CACHE_DIR:-$HOME/.cache/olcrtc}"
|
||||
GOMOD_CACHE="$CACHE_DIR/gomod"
|
||||
GO_BUILD_CACHE="$CACHE_DIR/gobuild"
|
||||
|
||||
if [ "$NO_CACHE" = "1" ]; then
|
||||
echo "[*] --no-cache: purging Go cache at $CACHE_DIR"
|
||||
chmod -R u+w "$GOMOD_CACHE" "$GO_BUILD_CACHE" 2>/dev/null || true
|
||||
if ! rm -rf "$GOMOD_CACHE" "$GO_BUILD_CACHE" 2>/dev/null; then
|
||||
echo "[*] Falling back to in-container purge (files owned by container UID)..."
|
||||
podman run --rm \
|
||||
-v "$CACHE_DIR":/cache:Z \
|
||||
"$IMAGE_NAME" \
|
||||
sh -c 'rm -rf /cache/gomod /cache/gobuild'
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "$GOMOD_CACHE" "$GO_BUILD_CACHE"
|
||||
echo "[*] Using Go cache: $CACHE_DIR"
|
||||
|
||||
echo "[*] Cloning repository..."
|
||||
git clone --depth 1 --recurse-submodules --branch "$BRANCH" "$REPO_URL" "$WORK_DIR"
|
||||
|
||||
echo "[*] Pulling Go image..."
|
||||
podman pull "$IMAGE_NAME"
|
||||
|
||||
echo "[*] Building OlcRTC..."
|
||||
podman run --rm \
|
||||
--network host \
|
||||
-v "$WORK_DIR":/app:Z \
|
||||
-v "$GOMOD_CACHE":/go/pkg/mod:Z \
|
||||
-v "$GO_BUILD_CACHE":/root/.cache/go-build:Z \
|
||||
-w /app \
|
||||
"$IMAGE_NAME" \
|
||||
sh -c "go mod download && go build -trimpath -ldflags='-s -w' -o olcrtc ./cmd/olcrtc"
|
||||
|
||||
if [ ! -f "$WORK_DIR/olcrtc" ]; then
|
||||
echo "[X] Build failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Generate YAML config
|
||||
CONFIG_FILE="$WORK_DIR/client.yaml"
|
||||
cat > "$CONFIG_FILE" <<EOF
|
||||
mode: cnc
|
||||
auth:
|
||||
provider: "$AUTH"
|
||||
room:
|
||||
id: "$ROOM_ID"
|
||||
crypto:
|
||||
key: "$KEY"
|
||||
net:
|
||||
transport: "$TRANSPORT"
|
||||
dns: "$DNS"
|
||||
socks:
|
||||
host: "$SOCKS_IP"
|
||||
port: $SOCKS_PORT
|
||||
EOF
|
||||
|
||||
if [ -n "$SOCKS_USER" ]; then
|
||||
cat >> "$CONFIG_FILE" <<EOF
|
||||
user: "$SOCKS_USER"
|
||||
pass: "$SOCKS_PASS"
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "$TRANSPORT" = "vp8channel" ]; then
|
||||
cat >> "$CONFIG_FILE" <<EOF
|
||||
vp8:
|
||||
fps: $VP8_FPS
|
||||
batch_size: $VP8_BATCH
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "$TRANSPORT" = "seichannel" ]; then
|
||||
cat >> "$CONFIG_FILE" <<EOF
|
||||
sei:
|
||||
fps: $SEI_FPS
|
||||
batch_size: $SEI_BATCH
|
||||
fragment_size: $SEI_FRAG
|
||||
ack_timeout_ms: $SEI_ACK
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "$TRANSPORT" = "videochannel" ]; then
|
||||
cat >> "$CONFIG_FILE" <<EOF
|
||||
video:
|
||||
width: $VIDEO_W
|
||||
height: $VIDEO_H
|
||||
fps: $VIDEO_FPS
|
||||
bitrate: "$VIDEO_BITRATE"
|
||||
hw: $VIDEO_HW
|
||||
codec: $VIDEO_CODEC
|
||||
qr_size: $VIDEO_QR_SIZE
|
||||
qr_recovery: $VIDEO_QR_RECOVERY
|
||||
tile_module: $VIDEO_TILE_MODULE
|
||||
tile_rs: $VIDEO_TILE_RS
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat >> "$CONFIG_FILE" <<EOF
|
||||
data: data
|
||||
debug: false
|
||||
EOF
|
||||
|
||||
echo "[*] Starting OlcRTC client..."
|
||||
START_CMD="./olcrtc client.yaml"
|
||||
if [ "$TRANSPORT" = "videochannel" ]; then
|
||||
START_CMD="apk add --no-cache ffmpeg >/dev/null && ./olcrtc client.yaml"
|
||||
fi
|
||||
podman run -d \
|
||||
--name "$CONTAINER_NAME" \
|
||||
--network host \
|
||||
--restart unless-stopped \
|
||||
-v "$WORK_DIR":/app:Z \
|
||||
-w /app \
|
||||
"$IMAGE_NAME" \
|
||||
sh -c "$START_CMD"
|
||||
|
||||
sleep 2
|
||||
|
||||
echo ""
|
||||
echo "[+] Client started successfully!"
|
||||
echo ""
|
||||
echo "Container name: $CONTAINER_NAME"
|
||||
echo "Auth: $AUTH"
|
||||
echo "Transport: $TRANSPORT"
|
||||
echo "Room ID/URL: $ROOM_ID"
|
||||
if [ -n "$SOCKS_USER" ]; then
|
||||
echo "SOCKS5 proxy: $SOCKS_IP:$SOCKS_PORT (auth: $SOCKS_USER)"
|
||||
else
|
||||
echo "SOCKS5 proxy: $SOCKS_IP:$SOCKS_PORT"
|
||||
fi
|
||||
echo ""
|
||||
echo "View logs:"
|
||||
echo " podman logs -f $CONTAINER_NAME"
|
||||
echo ""
|
||||
echo "Stop client:"
|
||||
echo " podman stop $CONTAINER_NAME"
|
||||
echo ""
|
||||
echo "Test proxy:"
|
||||
if [ -n "$SOCKS_USER" ]; then
|
||||
echo " curl --socks5-hostname $SOCKS_USER:$SOCKS_PASS@$SOCKS_IP:$SOCKS_PORT https://icanhazip.com"
|
||||
else
|
||||
echo " curl --socks5-hostname $SOCKS_IP:$SOCKS_PORT https://icanhazip.com"
|
||||
fi
|
||||
echo ""
|
||||
@@ -1,175 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
die() {
|
||||
echo "olcrtc-entrypoint: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ "${1:-}" = "olcrtc" ]; then
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
exec /usr/local/bin/olcrtc "$@"
|
||||
fi
|
||||
|
||||
mode="${OLCRTC_MODE:-srv}"
|
||||
room_id="${OLCRTC_ROOM_ID:-}"
|
||||
carrier="${OLCRTC_CARRIER:-${OLCRTC_AUTH:-}}"
|
||||
transport="${OLCRTC_TRANSPORT:-}"
|
||||
data_dir="${OLCRTC_DATA_DIR:-/usr/share/olcrtc}"
|
||||
dns_server="${OLCRTC_DNS:-8.8.8.8:53}"
|
||||
key="${OLCRTC_KEY:-}"
|
||||
key_file="${OLCRTC_KEY_FILE:-/var/lib/olcrtc/key.hex}"
|
||||
socks_proxy="${OLCRTC_SOCKS_PROXY:-}"
|
||||
socks_proxy_port="${OLCRTC_SOCKS_PROXY_PORT:-1080}"
|
||||
socks_host="${OLCRTC_SOCKS_HOST:-127.0.0.1}"
|
||||
socks_port="${OLCRTC_SOCKS_PORT:-8808}"
|
||||
socks_user="${OLCRTC_SOCKS_USER:-}"
|
||||
socks_pass="${OLCRTC_SOCKS_PASS:-}"
|
||||
|
||||
video_w="${OLCRTC_VIDEO_W:-0}"
|
||||
video_h="${OLCRTC_VIDEO_H:-0}"
|
||||
video_fps="${OLCRTC_VIDEO_FPS:-0}"
|
||||
video_bitrate="${OLCRTC_VIDEO_BITRATE:-}"
|
||||
video_hw="${OLCRTC_VIDEO_HW:-none}"
|
||||
video_codec="${OLCRTC_VIDEO_CODEC:-qrcode}"
|
||||
video_qr_size="${OLCRTC_VIDEO_QR_SIZE:-0}"
|
||||
video_qr_recovery="${OLCRTC_VIDEO_QR_RECOVERY:-low}"
|
||||
video_tile_module="${OLCRTC_VIDEO_TILE_MODULE:-0}"
|
||||
video_tile_rs="${OLCRTC_VIDEO_TILE_RS:-0}"
|
||||
|
||||
vp8_fps="${OLCRTC_VP8_FPS:-0}"
|
||||
vp8_batch="${OLCRTC_VP8_BATCH:-0}"
|
||||
|
||||
sei_fps="${OLCRTC_SEI_FPS:-0}"
|
||||
sei_batch="${OLCRTC_SEI_BATCH:-0}"
|
||||
sei_frag="${OLCRTC_SEI_FRAG:-0}"
|
||||
sei_ack="${OLCRTC_SEI_ACK:-0}"
|
||||
|
||||
debug="${OLCRTC_DEBUG:-false}"
|
||||
ffmpeg="${OLCRTC_FFMPEG:-ffmpeg}"
|
||||
|
||||
case "$mode" in
|
||||
srv|cnc) ;;
|
||||
*) die "set OLCRTC_MODE to srv or cnc" ;;
|
||||
esac
|
||||
[ -n "$carrier" ] || die "set OLCRTC_CARRIER (e.g. jitsi, telemost, wbstream)"
|
||||
[ -n "$transport" ] || die "set OLCRTC_TRANSPORT (e.g. datachannel, videochannel, seichannel, vp8channel)"
|
||||
|
||||
make_key() {
|
||||
if command -v od >/dev/null 2>&1; then
|
||||
od -An -N32 -tx1 /dev/urandom | tr -d ' \n'
|
||||
else
|
||||
hexdump -n 32 -e '32/1 "%02x"' /dev/urandom
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -z "$room_id" ]; then
|
||||
die "set OLCRTC_ROOM_ID to the room identifier"
|
||||
fi
|
||||
|
||||
if [ -z "$key" ]; then
|
||||
if [ -s "$key_file" ]; then
|
||||
key="$(tr -d '[:space:]' < "$key_file")"
|
||||
elif [ "$mode" = "srv" ]; then
|
||||
key="$(make_key)"
|
||||
umask 077
|
||||
printf '%s\n' "$key" > "$key_file"
|
||||
echo "olcrtc-entrypoint: generated encryption key and saved it to $key_file" >&2
|
||||
echo "olcrtc-entrypoint: OLCRTC_KEY=$key" >&2
|
||||
else
|
||||
die "set OLCRTC_KEY or mount OLCRTC_KEY_FILE with the server encryption key"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$key" in
|
||||
*[!0-9a-fA-F]*)
|
||||
die "OLCRTC_KEY must be a 64-character hex string"
|
||||
;;
|
||||
esac
|
||||
|
||||
[ "${#key}" -eq 64 ] || die "OLCRTC_KEY must be 64 hex characters"
|
||||
|
||||
# Generate YAML config
|
||||
config="/tmp/olcrtc-${mode}.yaml"
|
||||
cat > "$config" <<EOF
|
||||
mode: $mode
|
||||
auth:
|
||||
provider: "$carrier"
|
||||
room:
|
||||
id: "$room_id"
|
||||
crypto:
|
||||
key: "$key"
|
||||
net:
|
||||
transport: "$transport"
|
||||
dns: "$dns_server"
|
||||
data: "$data_dir"
|
||||
EOF
|
||||
|
||||
if [ "$mode" = "srv" ] && [ -n "$socks_proxy" ]; then
|
||||
cat >> "$config" <<EOF
|
||||
socks:
|
||||
proxy_addr: "$socks_proxy"
|
||||
proxy_port: $socks_proxy_port
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "$mode" = "cnc" ]; then
|
||||
cat >> "$config" <<EOF
|
||||
socks:
|
||||
host: "$socks_host"
|
||||
port: $socks_port
|
||||
EOF
|
||||
if [ -n "$socks_user" ]; then
|
||||
cat >> "$config" <<EOF
|
||||
user: "$socks_user"
|
||||
pass: "$socks_pass"
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$transport" = "videochannel" ]; then
|
||||
cat >> "$config" <<EOF
|
||||
video:
|
||||
width: $video_w
|
||||
height: $video_h
|
||||
fps: $video_fps
|
||||
hw: $video_hw
|
||||
codec: $video_codec
|
||||
qr_recovery: $video_qr_recovery
|
||||
EOF
|
||||
[ -n "$video_bitrate" ] && printf ' bitrate: "%s"\n' "$video_bitrate" >> "$config"
|
||||
[ "$video_qr_size" -gt 0 ] 2>/dev/null && printf ' qr_size: %s\n' "$video_qr_size" >> "$config"
|
||||
[ "$video_tile_module" -gt 0 ] 2>/dev/null && printf ' tile_module: %s\n' "$video_tile_module" >> "$config"
|
||||
[ "$video_tile_rs" -gt 0 ] 2>/dev/null && printf ' tile_rs: %s\n' "$video_tile_rs" >> "$config"
|
||||
fi
|
||||
|
||||
if [ "$transport" = "vp8channel" ]; then
|
||||
cat >> "$config" <<EOF
|
||||
vp8:
|
||||
fps: $vp8_fps
|
||||
batch_size: $vp8_batch
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "$transport" = "seichannel" ]; then
|
||||
cat >> "$config" <<EOF
|
||||
sei:
|
||||
fps: $sei_fps
|
||||
batch_size: $sei_batch
|
||||
fragment_size: $sei_frag
|
||||
ack_timeout_ms: $sei_ack
|
||||
EOF
|
||||
fi
|
||||
|
||||
case "${debug}" in
|
||||
1|true|TRUE|yes|YES|on|ON)
|
||||
printf 'debug: true\n' >> "$config"
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -n "$ffmpeg" ] && printf 'ffmpeg: "%s"\n' "$ffmpeg" >> "$config"
|
||||
|
||||
exec /usr/local/bin/olcrtc "$config"
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
pidof olcrtc >/dev/null 2>&1
|
||||
532
script/srv.sh
532
script/srv.sh
@@ -1,532 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "ЕСЛИ У ВАС ЕСТЬ ПРОБЛЕМЫ - Я В КУРСЕ, ПРОЕКТ В БЕТЕ, ПО ПРОБЛЕМАМ В ЧАТ t.me/openlibrecommunity ИЛИ ВООБЩЕ НЕКУДА, ЖДИТЕ РЕЛИЗА"
|
||||
|
||||
set -e
|
||||
|
||||
PODMAN_ID=$(tr -dc 'a-z0-9' </dev/urandom | head -c 8)
|
||||
CONTAINER_NAME="olcrtc-server-$PODMAN_ID"
|
||||
IMAGE_NAME="docker.io/library/golang:1.26-alpine3.22"
|
||||
REPO_URL="https://github.com/openlibrecommunity/olcrtc.git"
|
||||
WORK_DIR="/tmp/olcrtc-deploy-$PODMAN_ID"
|
||||
BRANCH="master"
|
||||
NO_CACHE=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--branch=*)
|
||||
BRANCH="${1#*=}"
|
||||
shift
|
||||
;;
|
||||
--no-cache)
|
||||
NO_CACHE=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "=== OlcRTC Server Deployment Script ==="
|
||||
echo ""
|
||||
echo "[*] Using branch: $BRANCH"
|
||||
echo ""
|
||||
|
||||
if ! command -v podman &> /dev/null; then
|
||||
echo "[!] Installing Podman..."
|
||||
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
SUDO=""
|
||||
elif command -v sudo &> /dev/null; then
|
||||
SUDO="sudo"
|
||||
elif command -v doas &> /dev/null; then
|
||||
SUDO="doas"
|
||||
else
|
||||
echo "[X] No sudo/doas found and not running as root. Cannot install podman."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if command -v apt &> /dev/null; then
|
||||
echo "[*] Detected apt (Debian/Ubuntu)"
|
||||
$SUDO apt update
|
||||
$SUDO apt install -y podman
|
||||
elif command -v dnf &> /dev/null; then
|
||||
echo "[*] Detected dnf (Fedora/RHEL)"
|
||||
$SUDO dnf install -y podman
|
||||
elif command -v yum &> /dev/null; then
|
||||
echo "[*] Detected yum (CentOS/RHEL)"
|
||||
$SUDO yum install -y podman
|
||||
elif command -v pacman &> /dev/null; then
|
||||
echo "[*] Detected pacman (Arch)"
|
||||
$SUDO pacman -Sy --noconfirm podman
|
||||
else
|
||||
echo "[X] Unsupported package manager. Install podman manually."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "[+] Using Podman"
|
||||
echo ""
|
||||
|
||||
validate_key() {
|
||||
case "$1" in
|
||||
*[!0-9a-fA-F]*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
[ "${#1}" -eq 64 ]
|
||||
}
|
||||
|
||||
echo "Select carrier:"
|
||||
echo " 1) jitsi"
|
||||
echo " 2) telemost"
|
||||
echo " 3) wbstream"
|
||||
read -p "Enter choice [1-3, default: 1]: " CARRIER_CHOICE
|
||||
|
||||
case "$CARRIER_CHOICE" in
|
||||
2)
|
||||
CARRIER="telemost"
|
||||
;;
|
||||
3)
|
||||
CARRIER="wbstream"
|
||||
;;
|
||||
*)
|
||||
CARRIER="jitsi"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "[*] Using carrier: $CARRIER"
|
||||
echo ""
|
||||
|
||||
echo "Select transport:"
|
||||
echo " 1) datachannel"
|
||||
echo " 2) videochannel"
|
||||
echo " 3) seichannel"
|
||||
echo " 4) vp8channel"
|
||||
read -p "Enter choice [1-4, default: 1]: " TRANSPORT_CHOICE
|
||||
|
||||
case "$TRANSPORT_CHOICE" in
|
||||
2)
|
||||
TRANSPORT="videochannel"
|
||||
;;
|
||||
3)
|
||||
TRANSPORT="seichannel"
|
||||
;;
|
||||
4)
|
||||
TRANSPORT="vp8channel"
|
||||
;;
|
||||
*)
|
||||
TRANSPORT="datachannel"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "[*] Using transport: $TRANSPORT"
|
||||
echo ""
|
||||
|
||||
GEN_ROOM=0
|
||||
|
||||
if [ "$CARRIER" = "jitsi" ]; then
|
||||
echo ""
|
||||
echo "Выберите Jitsi-сервер (проверьте в браузере, какой работает в вашей сети):"
|
||||
echo " 1) https://meet.small-dm.ru/"
|
||||
echo " 2) https://meet1.arbitr.ru/"
|
||||
echo " 3) https://meet.handyweb.org/"
|
||||
echo " 4) Другой (ввести вручную)"
|
||||
read -p "Введите номер [1-4, по умолчанию: 1]: " JITSI_SERVER_CHOICE
|
||||
|
||||
case "$JITSI_SERVER_CHOICE" in
|
||||
2)
|
||||
JITSI_BASE_URL="https://meet1.arbitr.ru"
|
||||
;;
|
||||
3)
|
||||
JITSI_BASE_URL="https://meet.handyweb.org"
|
||||
;;
|
||||
4)
|
||||
read -p "Введите URL Jitsi-сервера: " JITSI_BASE_INPUT
|
||||
JITSI_BASE_URL="${JITSI_BASE_INPUT%/}"
|
||||
if [ -z "$JITSI_BASE_URL" ]; then
|
||||
echo "[X] URL не может быть пустым"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
JITSI_BASE_URL="https://meet.small-dm.ru"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Room options:"
|
||||
echo " 1) Auto-generate new room (recommended)"
|
||||
echo " 2) Use specific room name or URL"
|
||||
read -p "Enter choice [1-2, default: 1]: " ROOM_CHOICE
|
||||
|
||||
case "$ROOM_CHOICE" in
|
||||
2)
|
||||
read -p "Enter Jitsi room name or URL: " JITSI_ROOM_INPUT
|
||||
if [ -z "$JITSI_ROOM_INPUT" ]; then
|
||||
echo "[X] Jitsi room name/URL cannot be empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$JITSI_ROOM_INPUT" in
|
||||
http://*|https://*|*/*)
|
||||
ROOM_ID="$JITSI_ROOM_INPUT"
|
||||
;;
|
||||
*)
|
||||
ROOM_ID="$JITSI_BASE_URL/$JITSI_ROOM_INPUT"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
JITSI_ROOM="olcrtc-$PODMAN_ID"
|
||||
ROOM_ID="$JITSI_BASE_URL/$JITSI_ROOM"
|
||||
echo "[*] Generated Jitsi room URL: $ROOM_ID"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
read -p "Enter Room ID: " ROOM_ID
|
||||
if [ -z "$ROOM_ID" ]; then
|
||||
echo "[X] Room ID/URL cannot be empty"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
read -p "DNS server [default: 8.8.8.8:53]: " DNS_INPUT
|
||||
DNS=${DNS_INPUT:-8.8.8.8:53}
|
||||
|
||||
echo ""
|
||||
read -p "Use SOCKS5 proxy for egress? (y/N): " USE_PROXY
|
||||
|
||||
SOCKS_PROXY_ADDR=""
|
||||
SOCKS_PROXY_PORT=0
|
||||
|
||||
if [[ "$USE_PROXY" =~ ^[Yy]$ ]]; then
|
||||
read -p "Enter SOCKS5 proxy address [default: 127.0.0.1]: " PROXY_ADDR_INPUT
|
||||
SOCKS_PROXY_ADDR=${PROXY_ADDR_INPUT:-127.0.0.1}
|
||||
|
||||
read -p "Enter SOCKS5 proxy port [default: 1080]: " PROXY_PORT_INPUT
|
||||
SOCKS_PROXY_PORT=${PROXY_PORT_INPUT:-1080}
|
||||
|
||||
echo "[*] Will use SOCKS5 proxy: $SOCKS_PROXY_ADDR:$SOCKS_PROXY_PORT"
|
||||
fi
|
||||
|
||||
# Transport-specific settings
|
||||
VIDEO_W=1920; VIDEO_H=1080; VIDEO_FPS=30; VIDEO_BITRATE="2M"; VIDEO_HW="none"
|
||||
VIDEO_CODEC="qrcode"; VIDEO_QR_SIZE=0; VIDEO_QR_RECOVERY="low"
|
||||
VIDEO_TILE_MODULE=4; VIDEO_TILE_RS=20
|
||||
VP8_FPS=25; VP8_BATCH=1
|
||||
SEI_FPS=60; SEI_BATCH=64; SEI_FRAG=900; SEI_ACK=2000
|
||||
|
||||
if [ "$TRANSPORT" = "videochannel" ]; then
|
||||
echo ""
|
||||
echo "--- Videochannel settings ---"
|
||||
|
||||
echo ""
|
||||
echo "Video codec:"
|
||||
echo " 1) qrcode"
|
||||
echo " 2) tile (requires 1080x1080)"
|
||||
read -p "Enter choice [1-2, default: 1]: " VCODEC_CHOICE
|
||||
|
||||
case "$VCODEC_CHOICE" in
|
||||
2)
|
||||
VIDEO_CODEC="tile"
|
||||
VIDEO_W=1080
|
||||
VIDEO_H=1080
|
||||
echo "[*] Tile codec selected - forcing 1080x1080"
|
||||
|
||||
read -p "Tile module size in pixels 1..270 [default: 4]: " VTILE_MOD_INPUT
|
||||
VIDEO_TILE_MODULE=${VTILE_MOD_INPUT:-4}
|
||||
|
||||
read -p "Tile Reed-Solomon parity percent 0..200 [default: 20]: " VTILE_RS_INPUT
|
||||
VIDEO_TILE_RS=${VTILE_RS_INPUT:-20}
|
||||
;;
|
||||
*)
|
||||
VIDEO_CODEC="qrcode"
|
||||
|
||||
read -p "Video width [default: 1920]: " VW_INPUT
|
||||
VIDEO_W=${VW_INPUT:-1920}
|
||||
|
||||
read -p "Video height [default: 1080]: " VH_INPUT
|
||||
VIDEO_H=${VH_INPUT:-1080}
|
||||
|
||||
read -p "QR error correction (low/medium/high/highest) [default: low]: " VQREC_INPUT
|
||||
VIDEO_QR_RECOVERY=${VQREC_INPUT:-low}
|
||||
|
||||
read -p "QR fragment size bytes [default: 0 (auto)]: " VQRSZ_INPUT
|
||||
VIDEO_QR_SIZE=${VQRSZ_INPUT:-0}
|
||||
;;
|
||||
esac
|
||||
|
||||
read -p "Video FPS [default: 30]: " VFPS_INPUT
|
||||
VIDEO_FPS=${VFPS_INPUT:-30}
|
||||
|
||||
read -p "Video bitrate [default: 2M]: " VBRT_INPUT
|
||||
VIDEO_BITRATE=${VBRT_INPUT:-2M}
|
||||
|
||||
read -p "Hardware acceleration (none/nvenc) [default: none]: " VHW_INPUT
|
||||
VIDEO_HW=${VHW_INPUT:-none}
|
||||
fi
|
||||
|
||||
if [ "$TRANSPORT" = "vp8channel" ]; then
|
||||
echo ""
|
||||
echo "--- VP8channel settings ---"
|
||||
|
||||
read -p "VP8 FPS [default: 25]: " VP8FPS_INPUT
|
||||
VP8_FPS=${VP8FPS_INPUT:-25}
|
||||
|
||||
read -p "VP8 batch size (frames per tick) [default: 1]: " VP8BATCH_INPUT
|
||||
VP8_BATCH=${VP8BATCH_INPUT:-1}
|
||||
fi
|
||||
|
||||
if [ "$TRANSPORT" = "seichannel" ]; then
|
||||
echo ""
|
||||
echo "--- SEIchannel settings ---"
|
||||
|
||||
read -p "SEI FPS [default: 60]: " SEIFPS_INPUT
|
||||
SEI_FPS=${SEIFPS_INPUT:-60}
|
||||
|
||||
read -p "SEI batch size (frames per tick) [default: 64]: " SEIBATCH_INPUT
|
||||
SEI_BATCH=${SEIBATCH_INPUT:-64}
|
||||
|
||||
read -p "SEI fragment size in bytes [default: 900]: " SEIFRAG_INPUT
|
||||
SEI_FRAG=${SEIFRAG_INPUT:-900}
|
||||
|
||||
read -p "SEI ACK timeout in milliseconds [default: 2000]: " SEIACK_INPUT
|
||||
SEI_ACK=${SEIACK_INPUT:-2000}
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "[*] Cleaning workspace..."
|
||||
rm -rf "$WORK_DIR"
|
||||
mkdir -p "$WORK_DIR"
|
||||
|
||||
CACHE_DIR="${OLCRTC_CACHE_DIR:-$HOME/.cache/olcrtc}"
|
||||
GOMOD_CACHE="$CACHE_DIR/gomod"
|
||||
GO_BUILD_CACHE="$CACHE_DIR/gobuild"
|
||||
|
||||
if [ "$NO_CACHE" = "1" ]; then
|
||||
echo "[*] --no-cache: purging Go cache at $CACHE_DIR"
|
||||
chmod -R u+w "$GOMOD_CACHE" "$GO_BUILD_CACHE" 2>/dev/null || true
|
||||
if ! rm -rf "$GOMOD_CACHE" "$GO_BUILD_CACHE" 2>/dev/null; then
|
||||
echo "[*] Falling back to in-container purge (files owned by container UID)..."
|
||||
podman run --rm \
|
||||
-v "$CACHE_DIR":/cache:Z \
|
||||
"$IMAGE_NAME" \
|
||||
sh -c 'rm -rf /cache/gomod /cache/gobuild'
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "$GOMOD_CACHE" "$GO_BUILD_CACHE"
|
||||
echo "[*] Using Go cache: $CACHE_DIR"
|
||||
|
||||
echo "[*] Cloning repository..."
|
||||
git clone --depth 1 --recurse-submodules --branch "$BRANCH" "$REPO_URL" "$WORK_DIR"
|
||||
|
||||
echo "[*] Pulling Go image..."
|
||||
podman pull "$IMAGE_NAME"
|
||||
|
||||
echo "[*] Building OlcRTC..."
|
||||
podman run --rm \
|
||||
--network host \
|
||||
-v "$WORK_DIR":/app:Z \
|
||||
-v "$GOMOD_CACHE":/go/pkg/mod:Z \
|
||||
-v "$GO_BUILD_CACHE":/root/.cache/go-build:Z \
|
||||
-w /app \
|
||||
"$IMAGE_NAME" \
|
||||
sh -c "go mod download && go build -trimpath -ldflags='-s -w' -o olcrtc ./cmd/olcrtc"
|
||||
|
||||
if [ ! -f "$WORK_DIR/olcrtc" ]; then
|
||||
echo "[X] Build failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$GEN_ROOM" = "1" ]; then
|
||||
echo "[*] Generating room via mode: gen..."
|
||||
GEN_CONFIG="$WORK_DIR/gen.yaml"
|
||||
cat > "$GEN_CONFIG" <<GENEOF
|
||||
mode: gen
|
||||
auth:
|
||||
provider: "$CARRIER"
|
||||
net:
|
||||
dns: "$DNS"
|
||||
gen:
|
||||
amount: 1
|
||||
data: data
|
||||
GENEOF
|
||||
ROOM_ID=$(podman run --rm \
|
||||
--network host \
|
||||
-v "$WORK_DIR":/app:Z \
|
||||
-w /app \
|
||||
"$IMAGE_NAME" \
|
||||
./olcrtc gen.yaml)
|
||||
if [ -z "$ROOM_ID" ]; then
|
||||
echo "[X] Room generation failed"
|
||||
exit 1
|
||||
fi
|
||||
echo "[+] Generated room ID: $ROOM_ID"
|
||||
fi
|
||||
|
||||
KEY_FILE="$HOME/.olcrtc_key"
|
||||
|
||||
if [ -f "$KEY_FILE" ]; then
|
||||
echo "[*] Loading existing encryption key..."
|
||||
KEY=$(tr -d '[:space:]' < "$KEY_FILE")
|
||||
if ! validate_key "$KEY"; then
|
||||
echo "[X] Invalid encryption key in $KEY_FILE"
|
||||
echo " Remove the file to generate a new key, or replace it with 64 hex characters."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "[*] Generating new encryption key..."
|
||||
KEY=$(openssl rand -hex 32)
|
||||
echo "$KEY" > "$KEY_FILE"
|
||||
chmod 600 "$KEY_FILE"
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "NEW ENCRYPTION KEY (saved to $KEY_FILE):"
|
||||
echo "$KEY"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Generate YAML config
|
||||
CONFIG_FILE="$WORK_DIR/server.yaml"
|
||||
cat > "$CONFIG_FILE" <<EOF
|
||||
mode: srv
|
||||
auth:
|
||||
provider: "$CARRIER"
|
||||
room:
|
||||
id: "$ROOM_ID"
|
||||
crypto:
|
||||
key: "$KEY"
|
||||
net:
|
||||
transport: "$TRANSPORT"
|
||||
dns: "$DNS"
|
||||
EOF
|
||||
|
||||
if [ -n "$SOCKS_PROXY_ADDR" ]; then
|
||||
cat >> "$CONFIG_FILE" <<EOF
|
||||
socks:
|
||||
proxy_addr: "$SOCKS_PROXY_ADDR"
|
||||
proxy_port: $SOCKS_PROXY_PORT
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "$TRANSPORT" = "vp8channel" ]; then
|
||||
cat >> "$CONFIG_FILE" <<EOF
|
||||
vp8:
|
||||
fps: $VP8_FPS
|
||||
batch_size: $VP8_BATCH
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "$TRANSPORT" = "seichannel" ]; then
|
||||
cat >> "$CONFIG_FILE" <<EOF
|
||||
sei:
|
||||
fps: $SEI_FPS
|
||||
batch_size: $SEI_BATCH
|
||||
fragment_size: $SEI_FRAG
|
||||
ack_timeout_ms: $SEI_ACK
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "$TRANSPORT" = "videochannel" ]; then
|
||||
cat >> "$CONFIG_FILE" <<EOF
|
||||
video:
|
||||
width: $VIDEO_W
|
||||
height: $VIDEO_H
|
||||
fps: $VIDEO_FPS
|
||||
bitrate: "$VIDEO_BITRATE"
|
||||
hw: $VIDEO_HW
|
||||
codec: $VIDEO_CODEC
|
||||
qr_size: $VIDEO_QR_SIZE
|
||||
qr_recovery: $VIDEO_QR_RECOVERY
|
||||
tile_module: $VIDEO_TILE_MODULE
|
||||
tile_rs: $VIDEO_TILE_RS
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat >> "$CONFIG_FILE" <<EOF
|
||||
data: data
|
||||
debug: false
|
||||
EOF
|
||||
|
||||
echo "[*] Starting OlcRTC server..."
|
||||
START_CMD="./olcrtc server.yaml"
|
||||
if [ "$TRANSPORT" = "videochannel" ]; then
|
||||
START_CMD="apk add --no-cache ffmpeg >/dev/null && ./olcrtc server.yaml"
|
||||
fi
|
||||
podman run -d \
|
||||
--network host \
|
||||
--name "$CONTAINER_NAME" \
|
||||
--restart unless-stopped \
|
||||
-v "$WORK_DIR":/app:Z \
|
||||
-w /app \
|
||||
"$IMAGE_NAME" \
|
||||
sh -c "$START_CMD"
|
||||
|
||||
read -p "Enter a comment for the config (default: olc - t.me/openlibrecommunity): " sub_configname
|
||||
if [ -z "$sub_configname" ]; then
|
||||
sub_configname="olc - t.me/openlibrecommunity"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "[+] Server started successfully!"
|
||||
echo ""
|
||||
echo "Container name: $CONTAINER_NAME"
|
||||
echo "Carrier: $CARRIER"
|
||||
echo "Transport: $TRANSPORT"
|
||||
echo "Room ID/URL: $ROOM_ID"
|
||||
echo "Encryption key: $KEY"
|
||||
echo ""
|
||||
TRANSPORT_PAYLOAD=""
|
||||
if [ "$TRANSPORT" = "vp8channel" ]; then
|
||||
TRANSPORT_PAYLOAD="<vp8-fps=${VP8_FPS}&vp8-batch=${VP8_BATCH}>"
|
||||
elif [ "$TRANSPORT" = "seichannel" ]; then
|
||||
TRANSPORT_PAYLOAD="<fps=${SEI_FPS}&batch=${SEI_BATCH}&frag=${SEI_FRAG}&ack-ms=${SEI_ACK}>"
|
||||
elif [ "$TRANSPORT" = "videochannel" ]; then
|
||||
TRANSPORT_PAYLOAD="<video-w=${VIDEO_W}&video-h=${VIDEO_H}&video-fps=${VIDEO_FPS}&video-bitrate=${VIDEO_BITRATE}&video-hw=${VIDEO_HW}&video-codec=${VIDEO_CODEC}>"
|
||||
if [ "$VIDEO_CODEC" = "tile" ]; then
|
||||
TRANSPORT_PAYLOAD="<video-w=${VIDEO_W}&video-h=${VIDEO_H}&video-fps=${VIDEO_FPS}&video-bitrate=${VIDEO_BITRATE}&video-hw=${VIDEO_HW}&video-codec=${VIDEO_CODEC}&video-tile-module=${VIDEO_TILE_MODULE}&video-tile-rs=${VIDEO_TILE_RS}>"
|
||||
elif [ "$VIDEO_QR_SIZE" -gt 0 ] 2>/dev/null; then
|
||||
TRANSPORT_PAYLOAD="<video-w=${VIDEO_W}&video-h=${VIDEO_H}&video-fps=${VIDEO_FPS}&video-bitrate=${VIDEO_BITRATE}&video-hw=${VIDEO_HW}&video-codec=${VIDEO_CODEC}&video-qr-recovery=${VIDEO_QR_RECOVERY}&video-qr-size=${VIDEO_QR_SIZE}>"
|
||||
else
|
||||
TRANSPORT_PAYLOAD="<video-w=${VIDEO_W}&video-h=${VIDEO_H}&video-fps=${VIDEO_FPS}&video-bitrate=${VIDEO_BITRATE}&video-hw=${VIDEO_HW}&video-codec=${VIDEO_CODEC}&video-qr-recovery=${VIDEO_QR_RECOVERY}>"
|
||||
fi
|
||||
fi
|
||||
|
||||
OLC_URI="olcrtc://$CARRIER?${TRANSPORT}${TRANSPORT_PAYLOAD}@$ROOM_ID#$KEY\$$sub_configname"
|
||||
echo "uri: $OLC_URI"
|
||||
echo ""
|
||||
|
||||
GR_BIN="$WORK_DIR/gr"
|
||||
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64) ARCH="amd64" ;;
|
||||
aarch64|arm64) ARCH="arm64" ;;
|
||||
esac
|
||||
GR_URL="https://github.com/zarazaex69/gr/releases/latest/download/gr-${OS}-${ARCH}"
|
||||
|
||||
if curl -fsSL "$GR_URL" -o "$GR_BIN" 2>/dev/null; then
|
||||
chmod +x "$GR_BIN"
|
||||
echo "[*] QR code for your URI (scan with olcbox):"
|
||||
echo ""
|
||||
"$GR_BIN" -o -s "$OLC_URI" 2>/dev/null || echo "[!] QR generation failed"
|
||||
echo ""
|
||||
else
|
||||
echo "[!] Could not download gr ($GR_URL), skipping QR"
|
||||
fi
|
||||
|
||||
if [ -n "$SOCKS_PROXY_ADDR" ]; then
|
||||
echo "SOCKS5 proxy: $SOCKS_PROXY_ADDR:$SOCKS_PROXY_PORT"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "View logs:"
|
||||
echo " podman logs -f $CONTAINER_NAME"
|
||||
echo ""
|
||||
echo "Stop server:"
|
||||
echo " podman stop $CONTAINER_NAME"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user