mirror of
https://github.com/MichaByte/OnBoard-Live.git
synced 2026-01-29 05:32:11 -05:00
major refactoring + docker progress
This commit is contained in:
parent
ecb8a80f8b
commit
e75f8c944a
35 changed files with 227 additions and 104 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -188,3 +188,4 @@ cython_debug/
|
||||||
|
|
||||||
*.dat
|
*.dat
|
||||||
dev.db*
|
dev.db*
|
||||||
|
.*env
|
||||||
|
|
|
||||||
11
active-stream-proxy/Dockerfile
Normal file
11
active-stream-proxy/Dockerfile
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
FROM python:3.12-alpine
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
COPY requirements.txt ./
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
CMD [ "python", "./main.py" ]
|
||||||
17
active-stream-proxy/main.py
Normal file
17
active-stream-proxy/main.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
import requests
|
||||||
|
|
||||||
|
active_stream = requests.get("http://backend:8000/api/v1/active_stream").text
|
||||||
|
old_active_stream = active_stream
|
||||||
|
|
||||||
|
proc = None
|
||||||
|
|
||||||
|
while True:
|
||||||
|
proc = subprocess.Popen([f"ffmpeg -re -i rtmp://mediamtx:1935/{active_stream} -c:a copy rtmp://host.containers.internal:1936/active-input"], shell=True)
|
||||||
|
time.sleep(3)
|
||||||
|
active_stream = requests.get("http://backend:8000/api/v1/active_stream").text
|
||||||
|
if old_active_stream is not active_stream:
|
||||||
|
proc.terminate()
|
||||||
|
proc = subprocess.Popen([f"ffmpeg -re -i rtmp://mediamtx:1935/{active_stream} -c:a copy rtmp://host.containers.internal:1936/active-input"], shell=True)
|
||||||
|
old_active_stream = active_stream
|
||||||
1
active-stream-proxy/requirements.txt
Normal file
1
active-stream-proxy/requirements.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
requests
|
||||||
21
backend/Dockerfile
Normal file
21
backend/Dockerfile
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
COPY requirements.txt ./
|
||||||
|
|
||||||
|
RUN apt-get update
|
||||||
|
|
||||||
|
RUN apt-get install -y python3-opencv
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY main.py schema.prisma .
|
||||||
|
|
||||||
|
COPY migrations .
|
||||||
|
|
||||||
|
RUN prisma generate
|
||||||
|
|
||||||
|
CMD [ "fastapi", "run", "main.py" ]
|
||||||
|
|
@ -83,7 +83,7 @@ async def get_recording_list(stream_key: str) -> List[str]:
|
||||||
recording["start"]
|
recording["start"]
|
||||||
for recording in (
|
for recording in (
|
||||||
await client.get(
|
await client.get(
|
||||||
f"http://localhost:9997/v3/recordings/get/{stream_key}"
|
f"http://{os.environ['MEDIAMTX_IP']}:9997/v3/recordings/get/{stream_key}"
|
||||||
)
|
)
|
||||||
).json()["segments"]
|
).json()["segments"]
|
||||||
]
|
]
|
||||||
|
|
@ -93,7 +93,7 @@ async def update_active():
|
||||||
global active_stream
|
global active_stream
|
||||||
global active_streams
|
global active_streams
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
streams_raw = (await client.get("http://localhost:9997/v3/paths/list")).json()[
|
streams_raw = (await client.get(f"http://{os.environ['MEDIAMTX_IP']}:9997/v3/paths/list")).json()[
|
||||||
"items"
|
"items"
|
||||||
]
|
]
|
||||||
streams = []
|
streams = []
|
||||||
|
|
@ -124,7 +124,7 @@ async def check_for_new():
|
||||||
global active_stream
|
global active_stream
|
||||||
global active_streams
|
global active_streams
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
streams_raw = (await client.get("http://localhost:9997/v3/paths/list")).json()[
|
streams_raw = (await client.get(f"http://{os.environ['MEDIAMTX_IP']}:9997/v3/paths/list")).json()[
|
||||||
"items"
|
"items"
|
||||||
]
|
]
|
||||||
streams_simple = []
|
streams_simple = []
|
||||||
|
|
@ -161,7 +161,7 @@ async def lifespan(app: FastAPI):
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
for stream in await db.stream.find_many():
|
for stream in await db.stream.find_many():
|
||||||
await client.post(
|
await client.post(
|
||||||
"http://127.0.0.1:9997/v3/config/paths/add/" + stream.key,
|
f"http://{os.environ['MEDIAMTX_IP']}:9997/v3/config/paths/add/" + stream.key,
|
||||||
json={"name": stream.key},
|
json={"name": stream.key},
|
||||||
)
|
)
|
||||||
yield
|
yield
|
||||||
|
|
@ -494,7 +494,7 @@ async def approve(ack, body):
|
||||||
)
|
)
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
await client.post(
|
await client.post(
|
||||||
"http://127.0.0.1:9997/v3/config/paths/add/" + new_stream.key,
|
f"http://{os.environ['MEDIAMTX_IP']}:9997/v3/config/paths/add/" + new_stream.key,
|
||||||
json={"name": new_stream.key},
|
json={"name": new_stream.key},
|
||||||
)
|
)
|
||||||
await bolt.client.chat_postMessage(
|
await bolt.client.chat_postMessage(
|
||||||
79
backend/requirements.txt
Normal file
79
backend/requirements.txt
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
aiofiles==24.1.0
|
||||||
|
aiohttp==3.9.5
|
||||||
|
aiosignal==1.3.1
|
||||||
|
annotated-types==0.7.0
|
||||||
|
anyio==4.4.0
|
||||||
|
APScheduler==3.10.4
|
||||||
|
attrs==23.2.0
|
||||||
|
black==24.4.2
|
||||||
|
build==1.2.1
|
||||||
|
certifi==2024.7.4
|
||||||
|
cffi==1.17.0
|
||||||
|
charset-normalizer==3.3.2
|
||||||
|
click==8.1.7
|
||||||
|
cryptography==43.0.0
|
||||||
|
defusedxml==0.8.0rc2
|
||||||
|
dnspython==2.6.1
|
||||||
|
ecdsa==0.19.0
|
||||||
|
email_validator==2.2.0
|
||||||
|
fastapi==0.112.0
|
||||||
|
fastapi-cli==0.0.4
|
||||||
|
fastapi-oauth2==1.0.0
|
||||||
|
fastapi-utils==0.7.0
|
||||||
|
frozenlist==1.4.1
|
||||||
|
h11==0.14.0
|
||||||
|
httpcore==1.0.5
|
||||||
|
httptools==0.6.1
|
||||||
|
httpx==0.27.0
|
||||||
|
idna==3.7
|
||||||
|
Jinja2==3.1.4
|
||||||
|
markdown-it-py==3.0.0
|
||||||
|
MarkupSafe==2.1.5
|
||||||
|
mdurl==0.1.2
|
||||||
|
multidict==6.0.5
|
||||||
|
mypy==1.11.0
|
||||||
|
mypy-extensions==1.0.0
|
||||||
|
nodeenv==1.9.1
|
||||||
|
numpy==2.1.0
|
||||||
|
oauthlib==3.2.2
|
||||||
|
opencv-python==4.10.0.84
|
||||||
|
packaging==24.1
|
||||||
|
pathspec==0.12.1
|
||||||
|
platformdirs==4.2.2
|
||||||
|
prisma==0.14.0
|
||||||
|
psutil==5.9.8
|
||||||
|
pyasn1==0.6.0
|
||||||
|
pycparser==2.22
|
||||||
|
pydantic==2.8.2
|
||||||
|
pydantic_core==2.20.1
|
||||||
|
Pygments==2.18.0
|
||||||
|
PyJWT==2.9.0
|
||||||
|
pyproject_hooks==1.1.0
|
||||||
|
python-dotenv==1.0.1
|
||||||
|
python-jose==3.3.0
|
||||||
|
python-multipart==0.0.9
|
||||||
|
python3-openid==3.2.0
|
||||||
|
pytz==2024.1
|
||||||
|
PyYAML==6.0.1
|
||||||
|
requests==2.32.3
|
||||||
|
requests-oauthlib==2.0.0
|
||||||
|
rich==13.7.1
|
||||||
|
rsa==4.9
|
||||||
|
shellingham==1.5.4
|
||||||
|
six==1.16.0
|
||||||
|
slack_bolt==1.20.0
|
||||||
|
slack_sdk==3.31.0
|
||||||
|
sniffio==1.3.1
|
||||||
|
social-auth-core==4.5.4
|
||||||
|
starlette==0.37.2
|
||||||
|
tomlkit==0.13.0
|
||||||
|
typer==0.12.3
|
||||||
|
typing-inspect==0.9.0
|
||||||
|
typing_extensions==4.12.2
|
||||||
|
tzlocal==5.2
|
||||||
|
urllib3==2.2.2
|
||||||
|
uvicorn==0.30.6
|
||||||
|
uvloop==0.19.0
|
||||||
|
watchfiles==0.22.0
|
||||||
|
websockets==12.0
|
||||||
|
yarl==1.9.4
|
||||||
|
|
@ -5,8 +5,8 @@ generator client {
|
||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
provider = "sqlite"
|
provider = "postgresql"
|
||||||
url = "file:./dev.db"
|
url = "file:./db/dev.db"
|
||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
42
docker-compose.yml
Normal file
42
docker-compose.yml
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
services:
|
||||||
|
mediamtx:
|
||||||
|
network_mode: host
|
||||||
|
build:
|
||||||
|
context: ./mediamtx
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
web-frontend:
|
||||||
|
build:
|
||||||
|
context: ./tiling-frontend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
volumes:
|
||||||
|
- tiling_frontend_build:/usr/src/app/dist
|
||||||
|
live-stream:
|
||||||
|
depends_on:
|
||||||
|
web-frontend:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
build:
|
||||||
|
context: ./live-stream
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
volumes:
|
||||||
|
- tiling_frontend_build:/html
|
||||||
|
environment:
|
||||||
|
YT_STREAM_KEY: ${YT_STREAM_KEY}
|
||||||
|
backend:
|
||||||
|
env_file: .backend.env
|
||||||
|
build:
|
||||||
|
context: ./backend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
volumes:
|
||||||
|
- ./backend/db:/usr/src/app/db
|
||||||
|
active-stream-proxy:
|
||||||
|
build:
|
||||||
|
context: ./active-stream-proxy
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
depends_on:
|
||||||
|
web-frontend:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
mediamtx:
|
||||||
|
condition: service_started
|
||||||
|
volumes:
|
||||||
|
mediamtx_recordings:
|
||||||
|
tiling_frontend_build:
|
||||||
7
live-stream/Dockerfile
Normal file
7
live-stream/Dockerfile
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
FROM alpine:3.20
|
||||||
|
|
||||||
|
RUN apk add --no-cache gstreamer gst-plugins-bad
|
||||||
|
|
||||||
|
RUN apk add --no-cache ffmpeg
|
||||||
|
|
||||||
|
ENTRYPOINT [""]
|
||||||
6
live-stream/run.sh
Normal file
6
live-stream/run.sh
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
gst-launch-1.0 -e wpesrc location="https://en.wikipedia.org/wiki/Main_Page" \
|
||||||
|
! videoconvert ! videoscale ! videorate \
|
||||||
|
! "video/x-raw, format=BGRA, width=854, height=480, framerate=30/1" \
|
||||||
|
! videoconvert \
|
||||||
|
! x264enc speed-preset=1 \
|
||||||
|
! filesink location=/dev/stdout | ffmpeg -re -y -i - -listen 1 -i rtmp://127.0.0.1:1936/active-input -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 -t 10 -f flv rtmp://x.rtmp.youtube.com/live2/no-way-am-i-doing-that-again
|
||||||
5
mediamtx/Dockerfile
Normal file
5
mediamtx/Dockerfile
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
FROM bluenviron/mediamtx
|
||||||
|
|
||||||
|
COPY . /
|
||||||
|
|
||||||
|
ENTRYPOINT ["/mediamtx"]
|
||||||
13
mediamtx/mediamtx.yml
Normal file
13
mediamtx/mediamtx.yml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
playback: yes
|
||||||
|
playbackAddress: :9996
|
||||||
|
playbackTrustedProxies: [ '127.0.0.1' ]
|
||||||
|
api: yes
|
||||||
|
pathDefaults:
|
||||||
|
record: yes
|
||||||
|
# Path of recording segments.
|
||||||
|
# Extension is added automatically.
|
||||||
|
# Available variables are %path (path name), %Y %m %d %H %M %S %f %s (time in strftime format)
|
||||||
|
recordPath: /recordings/%path/%Y-%m-%d_%H-%M-%S-%f
|
||||||
|
recordDeleteAfter: 0s
|
||||||
|
webrtcICEServers2:
|
||||||
|
- url: stun:stun.l.google.com:19302
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
[build-system]
|
|
||||||
requires = ["hatchling"]
|
|
||||||
build-backend = "hatchling.build"
|
|
||||||
|
|
||||||
[project]
|
|
||||||
name = "onboard_live_backend"
|
|
||||||
version = "0.0.1"
|
|
||||||
authors = [{ name = "Micha Albert", email = "micha@2231puppy.tech" }]
|
|
||||||
description = "Backend for OnBoard Live, A Hack Club YSWS grant program"
|
|
||||||
readme = "README.md"
|
|
||||||
requires-python = ">=3.9"
|
|
||||||
dependencies = [
|
|
||||||
"aiohttp==3.9.5",
|
|
||||||
"aiosignal==1.3.1",
|
|
||||||
"annotated-types==0.7.0",
|
|
||||||
"anyio==4.4.0",
|
|
||||||
"APScheduler==3.10.4",
|
|
||||||
"attrs==23.2.0",
|
|
||||||
"black==24.4.2",
|
|
||||||
"certifi==2024.7.4",
|
|
||||||
"cffi==1.17.0",
|
|
||||||
"charset-normalizer==3.3.2",
|
|
||||||
"click==8.1.7",
|
|
||||||
"cryptography==43.0.0",
|
|
||||||
"defusedxml==0.8.0rc2",
|
|
||||||
"dnspython==2.6.1",
|
|
||||||
"ecdsa==0.19.0",
|
|
||||||
"email_validator==2.2.0",
|
|
||||||
"fastapi==0.112.0",
|
|
||||||
"fastapi-cli==0.0.4",
|
|
||||||
"fastapi-oauth2==1.0.0",
|
|
||||||
"fastapi-utils==0.7.0",
|
|
||||||
"frozenlist==1.4.1",
|
|
||||||
"h11==0.14.0",
|
|
||||||
"httpcore==1.0.5",
|
|
||||||
"httptools==0.6.1",
|
|
||||||
"httpx==0.27.0",
|
|
||||||
"idna==3.7",
|
|
||||||
"Jinja2==3.1.4",
|
|
||||||
"markdown-it-py==3.0.0",
|
|
||||||
"MarkupSafe==2.1.5",
|
|
||||||
"mdurl==0.1.2",
|
|
||||||
"multidict==6.0.5",
|
|
||||||
"mypy==1.11.0",
|
|
||||||
"mypy-extensions==1.0.0",
|
|
||||||
"nodeenv==1.9.1",
|
|
||||||
"oauthlib==3.2.2",
|
|
||||||
"packaging==24.1",
|
|
||||||
"pathspec==0.12.1",
|
|
||||||
"platformdirs==4.2.2",
|
|
||||||
"prisma==0.14.0",
|
|
||||||
"psutil==5.9.8",
|
|
||||||
"pyasn1==0.6.0",
|
|
||||||
"pycparser==2.22",
|
|
||||||
"pydantic==2.8.2",
|
|
||||||
"pydantic_core==2.20.1",
|
|
||||||
"Pygments==2.18.0",
|
|
||||||
"PyJWT==2.9.0",
|
|
||||||
"python-dotenv==1.0.1",
|
|
||||||
"python-jose==3.3.0",
|
|
||||||
"python-multipart==0.0.9",
|
|
||||||
"python3-openid==3.2.0",
|
|
||||||
"pytz==2024.1",
|
|
||||||
"PyYAML==6.0.1",
|
|
||||||
"requests==2.32.3",
|
|
||||||
"requests-oauthlib==2.0.0",
|
|
||||||
"rich==13.7.1",
|
|
||||||
"rsa==4.9",
|
|
||||||
"shellingham==1.5.4",
|
|
||||||
"six==1.16.0",
|
|
||||||
"slack_bolt==1.20.0",
|
|
||||||
"slack_sdk==3.31.0",
|
|
||||||
"sniffio==1.3.1",
|
|
||||||
"social-auth-core==4.5.4",
|
|
||||||
"starlette==0.37.2",
|
|
||||||
"tomlkit==0.13.0",
|
|
||||||
"typer==0.12.3",
|
|
||||||
"typing-inspect==0.9.0",
|
|
||||||
"typing_extensions==4.12.2",
|
|
||||||
"tzlocal==5.2",
|
|
||||||
"urllib3==2.2.2",
|
|
||||||
"uvicorn[standard]==0.30.6",
|
|
||||||
"uvloop==0.19.0",
|
|
||||||
"watchfiles==0.22.0",
|
|
||||||
"websockets==12.0",
|
|
||||||
"yarl==1.9.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[project.urls]
|
|
||||||
Homepage = "https://github.com/MichaByte/OnBoard-Live"
|
|
||||||
|
|
||||||
[tool.hatch.build.targets.wheel]
|
|
||||||
packages = ["onboard_live_backend"]
|
|
||||||
|
|
||||||
[project.scripts]
|
|
||||||
onboard-live-backend-start = "onboard_live_backend.main:main"
|
|
||||||
16
tiling-frontend/Dockerfile
Normal file
16
tiling-frontend/Dockerfile
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
FROM docker.io/oven/bun:slim AS base
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
FROM base AS install
|
||||||
|
RUN mkdir -p /temp/dev
|
||||||
|
COPY package.json bun.lockb /temp/dev/
|
||||||
|
RUN cd /temp/dev && bun install
|
||||||
|
|
||||||
|
RUN mkdir -p /temp/prod
|
||||||
|
COPY package.json bun.lockb /temp/prod/
|
||||||
|
RUN cd /temp/prod && bun install --production
|
||||||
|
|
||||||
|
FROM base AS release
|
||||||
|
COPY --from=install /temp/dev/node_modules node_modules
|
||||||
|
COPY . .
|
||||||
|
RUN bun --bun run build
|
||||||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue