去除ws心跳机制,改为http
This commit is contained in:
parent
0aec02d3fe
commit
5bfa069b7a
@ -2,6 +2,8 @@
|
|||||||
ffmpeg_path = r"D:\software\ffmpeg\ffmpeg-4.4.1\bin\ffmpeg.exe"
|
ffmpeg_path = r"D:\software\ffmpeg\ffmpeg-4.4.1\bin\ffmpeg.exe"
|
||||||
cleanup_interval = 60 # 定时清理间隔时间(秒)
|
cleanup_interval = 60 # 定时清理间隔时间(秒)
|
||||||
expired_timeout = 60 * 1000 * 6 # 流空闲超时时间(毫秒)
|
expired_timeout = 60 * 1000 * 6 # 流空闲超时时间(毫秒)
|
||||||
rtmp_url = "rtmp://127.0.0.1/live"
|
srs_host = "127.0.0.1"
|
||||||
flv_url = "http://127.0.0.1:8080/live"
|
rtmp_url = f"rtmp://{srs_host}/live"
|
||||||
|
flv_url = f"http://{srs_host}:8080/live"
|
||||||
|
rtc_url = f"http://{srs_host}:1985/rtc/v1/whep/?app=live&stream="
|
||||||
md5_salt = "linxyun2024"
|
md5_salt = "linxyun2024"
|
@ -1,5 +1,5 @@
|
|||||||
from app.middleware.cors import add_cors_middleware
|
from app.middleware.cors import add_cors_middleware
|
||||||
from app.routes import websocket, stream
|
from app.routes import stream
|
||||||
from app.tasks.cleanup_task import cleanup_streams
|
from app.tasks.cleanup_task import cleanup_streams
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
@ -16,7 +16,7 @@ async def lifespan(app: FastAPI):
|
|||||||
|
|
||||||
# 创建 config
|
# 创建 config
|
||||||
config = Config(
|
config = Config(
|
||||||
entCode="57",
|
entCode="56",
|
||||||
project="smartroadlamp",
|
project="smartroadlamp",
|
||||||
role={
|
role={
|
||||||
"1101": ["/**"],
|
"1101": ["/**"],
|
||||||
@ -34,9 +34,8 @@ app = FastAPI(lifespan=lifespan)
|
|||||||
# 添加跨域中间件
|
# 添加跨域中间件
|
||||||
add_cors_middleware(app)
|
add_cors_middleware(app)
|
||||||
# 添加鉴权中间件
|
# 添加鉴权中间件
|
||||||
linxyun.add_security_middleware(app)
|
# linxyun.add_security_middleware(app)
|
||||||
|
|
||||||
app.include_router(websocket.router)
|
|
||||||
app.include_router(stream.router)
|
app.include_router(stream.router)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,17 +1,22 @@
|
|||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from app.services.stream_manager import stop_stream
|
from app.services.stream_manager import reset_stream_time
|
||||||
from app.services.ffmpeg_service import stream_rtsp_to_flv
|
from app.services.ffmpeg_service import stream_rtsp_to_url
|
||||||
from linxyun.utils.result import Result
|
from linxyun.utils.result import Result, SysCodes
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@router.get("/get_stream")
|
@router.get("/get_stream")
|
||||||
async def get_stream(camera_id: str):
|
async def get_stream(camera_id: str, type: str="flv"):
|
||||||
flv_url = await stream_rtsp_to_flv(camera_id)
|
url = await stream_rtsp_to_url(camera_id, type)
|
||||||
if flv_url is None:
|
if url is None:
|
||||||
return Result.error("0001", "Stream not started")
|
return Result.error(SysCodes.OPERATE_FAIL)
|
||||||
return Result.ok(flv_url)
|
return Result.ok(url)
|
||||||
|
|
||||||
|
@router.get("/looking/{camera_id}")
|
||||||
|
async def looking(camera_id: str):
|
||||||
|
status = reset_stream_time(camera_id)
|
||||||
|
if status is True:
|
||||||
|
return Result.ok()
|
||||||
|
else:
|
||||||
|
return Result.error(SysCodes.OPERATE_FAIL)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/stop_stream")
|
|
||||||
def stop(id: str):
|
|
||||||
stop_stream(id)
|
|
||||||
return {"message": "Stream stopped"}
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
# app/routes/websocket.py
|
|
||||||
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
|
|
||||||
from app.services.stream_manager import reset_stream_time
|
|
||||||
|
|
||||||
router = APIRouter()
|
|
||||||
|
|
||||||
@router.websocket("/ws")
|
|
||||||
async def websocket_endpoint(websocket: WebSocket):
|
|
||||||
await websocket.accept()
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
json_msg = await websocket.receive_json()
|
|
||||||
if json_msg:
|
|
||||||
reset_stream_time(json_msg.get("looking"))
|
|
||||||
await websocket.send_text("ok")
|
|
||||||
except WebSocketDisconnect:
|
|
||||||
print("WebSocket disconnected")
|
|
@ -1,12 +1,11 @@
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import time
|
import time
|
||||||
from app.config import ffmpeg_path, rtmp_url, flv_url
|
from app.config import ffmpeg_path, rtmp_url, flv_url, rtc_url
|
||||||
from app.services.stream_manager import stream_manager
|
from app.services.stream_manager import stream_manager
|
||||||
from app.utils.logger import get_logger
|
from app.utils.logger import get_logger
|
||||||
from app.utils.md5 import generate_md5
|
from app.utils.md5 import generate_md5
|
||||||
import subprocess
|
import subprocess
|
||||||
from urllib.parse import urljoin
|
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
test_url = "rtsp://admin:jitu0818@192.168.4.102:554/Streaming/Channels/101"
|
test_url = "rtsp://admin:jitu0818@192.168.4.102:554/Streaming/Channels/101"
|
||||||
@ -56,7 +55,7 @@ async def start_stream(stream_id: str, output_url: str):
|
|||||||
return process
|
return process
|
||||||
|
|
||||||
|
|
||||||
async def stream_rtsp_to_flv(stream_id: str):
|
async def stream_rtsp_to_url(stream_id: str, type: str="flv"):
|
||||||
md5_route = generate_md5(stream_id)
|
md5_route = generate_md5(stream_id)
|
||||||
output_url = f"{rtmp_url}/{md5_route}"
|
output_url = f"{rtmp_url}/{md5_route}"
|
||||||
# 如果流已经在运行,检查进程是否仍在运行
|
# 如果流已经在运行,检查进程是否仍在运行
|
||||||
@ -65,11 +64,15 @@ async def stream_rtsp_to_flv(stream_id: str):
|
|||||||
process = stream_manager[stream_id]["process"]
|
process = stream_manager[stream_id]["process"]
|
||||||
if process.poll() is None:
|
if process.poll() is None:
|
||||||
logger.info(f"Stream {stream_id} is still running.")
|
logger.info(f"Stream {stream_id} is still running.")
|
||||||
|
if type == "rtc":
|
||||||
|
return f"{rtc_url}{md5_route}.flv"
|
||||||
return f"{flv_url}/{md5_route}.flv"
|
return f"{flv_url}/{md5_route}.flv"
|
||||||
# 如果流未在运行,启动新流
|
# 如果流未在运行,启动新流
|
||||||
logger.info(f"Stream {stream_id} is not running. Starting new stream.")
|
logger.info(f"Stream {stream_id} is not running. Starting new stream.")
|
||||||
process = await start_stream(stream_id, output_url)
|
process = await start_stream(stream_id, output_url)
|
||||||
if process.poll() is None:
|
if process.poll() is None:
|
||||||
logger.info(f"Stream {stream_id} started successfully.")
|
logger.info(f"Stream {stream_id} started successfully.")
|
||||||
|
if type == "rtc":
|
||||||
|
return f"{rtc_url}{md5_route}.flv"
|
||||||
return f"{flv_url}/{md5_route}.flv"
|
return f"{flv_url}/{md5_route}.flv"
|
||||||
return None
|
return None
|
||||||
|
@ -4,11 +4,13 @@ stream_manager = {}
|
|||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
def reset_stream_time(stream_id: str):
|
def reset_stream_time(stream_id: str) -> bool:
|
||||||
if stream_id in stream_manager:
|
if stream_id in stream_manager:
|
||||||
new_time = int(time.time() * 1000)
|
new_time = int(time.time() * 1000)
|
||||||
logger.info(f"Stream {stream_id} reset time to {new_time}")
|
logger.info(f"Stream {stream_id} reset time to {new_time}")
|
||||||
stream_manager[stream_id]["create_time"] = new_time
|
stream_manager[stream_id]["create_time"] = new_time
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def stop_stream(stream_id: str):
|
def stop_stream(stream_id: str):
|
||||||
if stream_id in stream_manager:
|
if stream_id in stream_manager:
|
||||||
@ -18,3 +20,5 @@ def stop_stream(stream_id: str):
|
|||||||
logger.info(f"Stream {stream_id} stopped.")
|
logger.info(f"Stream {stream_id} stopped.")
|
||||||
del stream_manager[stream_id]
|
del stream_manager[stream_id]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ class SecurityMiddleware(BaseHTTPMiddleware):
|
|||||||
# 获取请求路径
|
# 获取请求路径
|
||||||
path = request.url.path
|
path = request.url.path
|
||||||
method = request.method
|
method = request.method
|
||||||
|
if method == "OPTIONS":
|
||||||
|
return await call_next(request)
|
||||||
logger.info(f"鉴权拦截: {method} {path}")
|
logger.info(f"鉴权拦截: {method} {path}")
|
||||||
# 获取请求头 Token
|
# 获取请求头 Token
|
||||||
token = request.headers.get("token")
|
token = request.headers.get("token")
|
||||||
|
@ -71,7 +71,7 @@ class Result:
|
|||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def ok(data):
|
def ok(data=None):
|
||||||
return Result("0000", "操作成功", data, True)
|
return Result("0000", "操作成功", data, True)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
Loading…
Reference in New Issue
Block a user