mirror of
https://github.com/MichaByte/OnBoard-Live.git
synced 2025-12-06 00:23:40 -05:00
major refactoring + docker progress
This commit is contained in:
parent
ecb8a80f8b
commit
e75f8c944a
35 changed files with 227 additions and 104 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -187,4 +187,5 @@ cython_debug/
|
|||
#.idea/
|
||||
|
||||
*.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"]
|
||||
for recording in (
|
||||
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"]
|
||||
]
|
||||
|
|
@ -93,7 +93,7 @@ async def update_active():
|
|||
global active_stream
|
||||
global active_streams
|
||||
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"
|
||||
]
|
||||
streams = []
|
||||
|
|
@ -124,7 +124,7 @@ async def check_for_new():
|
|||
global active_stream
|
||||
global active_streams
|
||||
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"
|
||||
]
|
||||
streams_simple = []
|
||||
|
|
@ -161,7 +161,7 @@ async def lifespan(app: FastAPI):
|
|||
async with httpx.AsyncClient() as client:
|
||||
for stream in await db.stream.find_many():
|
||||
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},
|
||||
)
|
||||
yield
|
||||
|
|
@ -494,7 +494,7 @@ async def approve(ack, body):
|
|||
)
|
||||
async with httpx.AsyncClient() as client:
|
||||
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},
|
||||
)
|
||||
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 {
|
||||
provider = "sqlite"
|
||||
url = "file:./dev.db"
|
||||
provider = "postgresql"
|
||||
url = "file:./db/dev.db"
|
||||
}
|
||||
|
||||
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