dedlepexa's picture
Update app.py
2e53b93 verified
Raw
History Blame Contribute Delete
3.5 kB
from fastapi import FastAPI, UploadFile
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
import cv2
import os
import numpy as np
import uvicorn
app = FastAPI()
FRAME_FOLDER = "frames"
MAP_W = 3
MAP_H = 2
ADMIN_KEY = "supersecret123"
os.makedirs(FRAME_FOLDER, exist_ok=True)
app.mount("/frames", StaticFiles(directory="frames"), name="frames")
current_streamer = None
@app.get("/", response_class=HTMLResponse)
def home(nick: str = "Unknown"):
return f"""
<html>
<body>
<h2>Вы: {nick}</h2>
<h3>Текущий стример: <span id="streamer">None</span></h3>
<button onclick="startStream()">START</button>
<button onclick="stopStream()">STOP</button>
<script>
let nick = "{nick}"
let running = false
let videoStream = null
async function updateStatus(){{
let r = await fetch("/status")
let data = await r.json()
document.getElementById("streamer").innerText = data.streamer
}}
setInterval(updateStatus,1000)
async function startStream(){{
let r = await fetch("/start?nick="+nick)
let data = await r.json()
if(data.error){{
alert(data.error)
return
}}
videoStream = await navigator.mediaDevices.getDisplayMedia({{
video:true
}})
const video = document.createElement("video")
video.srcObject = videoStream
video.play()
const canvas = document.createElement("canvas")
const ctx = canvas.getContext("2d")
running = true
async function sendFrame(){{
if(!running) return
canvas.width = 384
canvas.height = 256
ctx.drawImage(video,0,0,384,256)
canvas.toBlob(async blob => {{
const form = new FormData()
form.append("file", blob, "frame.jpg")
await fetch("/frame_upload", {{
method:"POST",
body:form
}})
}},"image/jpeg")
setTimeout(sendFrame,200)
}}
sendFrame()
}}
async function stopStream(){{
running=false
if(videoStream){{
videoStream.getTracks().forEach(t=>t.stop())
}}
await fetch("/stop?nick="+nick)
}}
</script>
</body>
</html>
"""
@app.get("/status")
def status():
return {"streamer": current_streamer}
@app.get("/start")
def start(nick: str):
global current_streamer
if current_streamer is not None:
return {"error": "Кто-то уже стримит!"}
current_streamer = nick
return {"ok": True}
@app.get("/stop")
def stop(nick: str):
global current_streamer
if current_streamer == nick:
current_streamer = None
return {"ok": True}
@app.post("/frame_upload")
async def frame_upload(file: UploadFile):
data = await file.read()
nparr = np.frombuffer(data, np.uint8)
frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
frame = cv2.resize(frame, (MAP_W*128, MAP_H*128))
for y in range(MAP_H):
for x in range(MAP_W):
tile = frame[
y*128:(y+1)*128,
x*128:(x+1)*128
]
map_id = y*MAP_W + x
path = f"{FRAME_FOLDER}/map{map_id}.jpg"
cv2.imwrite(path, tile)
return {"ok": True}
@app.get("/force_stop")
def force_stop(key: str):
global current_streamer
if key != ADMIN_KEY:
return {"error": "access denied"}
current_streamer = None
return {"status": "stream force stopped"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=7860)