Browse Source

rtsp 串流 & log 網址中文化

Mia 5 months ago
parent
commit
1130599574
3 changed files with 73 additions and 17 deletions
  1. 7 1
      README.md
  2. BIN
      __pycache__/main.cpython-312.pyc
  3. 66 16
      main.py

+ 7 - 1
README.md

@@ -3,4 +3,10 @@
 * ignore : static/、101evn/
 * speech2text.py 由 Tomoya 撰寫,其餘為 Mia
 * 安裝套件:pip install -r requirements.txt
-* 本API在cmm.ai:9101 上有做反向代理
+* 本API在cmm.ai:9101 上有做反向代理
+* ffmpeg指令:ffmpeg -rtsp_transport tcp -i rtsp://db.ptt.cx:8554/stream1 -buffer_size 100000k \
+       -c:v libx264 -c:a aac \
+       -f hls -hls_time 10 -hls_list_size 10 \
+       -hls_base_url https://cmm.ai:9101/segment/ \
+       -hls_segment_filename 'segment_%03d.ts' \
+       stream.m3u8

BIN
__pycache__/main.cpython-312.pyc


+ 66 - 16
main.py

@@ -1,4 +1,4 @@
-from fastapi import FastAPI, Form, UploadFile, File, HTTPException
+from fastapi import FastAPI, Form, UploadFile, File, HTTPException,  Request, Response
 import uvicorn
 from fastapi.middleware.cors import CORSMiddleware
 from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
@@ -9,32 +9,40 @@ from datetime import datetime
 from fastapi.responses import RedirectResponse
 import logging
 from logging.handlers import TimedRotatingFileHandler
+from urllib.parse import unquote
 
-# 設定日誌配置
 log_folder = 'log'
 log_file = f'{log_folder}/app.log'
 
-# 設定日誌格式
+# 日志格式
 log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
 date_format = '%Y-%m-%d %H:%M:%S'
 
-# 設定 TimedRotatingFileHandler
-handler = TimedRotatingFileHandler(
+class URLDecodingFormatter(logging.Formatter):
+    def format(self, record):
+        # 使用父类的 format 方法获取原始的日志消息
+        original_message = super().format(record)
+        # 解码 URL 编码部分
+        decoded_message = unquote(original_message)
+        return decoded_message
+
+# 清除所有默认处理器
+for handler in logging.root.handlers[:]:
+    logging.root.removeHandler(handler)
+
+# 创建日志处理器
+file_handler = TimedRotatingFileHandler(
     log_file,
     when='midnight',
     interval=1,
-    backupCount=14  # 保留7天的日誌
+    backupCount=14  # 保留14天的日志
 )
-handler.setFormatter(logging.Formatter(log_format, datefmt=date_format))
-
-# 設定根日誌
-logging.basicConfig(
-    handlers=[handler],
-    level=logging.INFO,
-    format=log_format,
-    datefmt=date_format
-)
-console_handler = logging.StreamHandler()
+file_handler.setFormatter(URLDecodingFormatter(log_format, datefmt=date_format))
+
+# 获取根日志对象并添加处理器
+logger = logging.getLogger()
+logger.setLevel(logging.INFO)
+logger.addHandler(file_handler)
 
 
 app = FastAPI()
@@ -129,6 +137,48 @@ async def image_check(image_file : UploadFile):
 
 
 
+from fastapi.responses import FileResponse
+
+
+@app.get("/stream.m3u8")
+async def get_m3u8():
+    return FileResponse("static/stream/stream.m3u8")
+
+# @app.get("/segment/{segment_name}")
+# async def get_segment(segment_name: str):
+#     return FileResponse(f"/home/mia/101/static/stream/segment_{segment_name}")
+
+app.mount("/segment", StaticFiles(directory="static/stream"), name="stream")
+
+from pathlib import Path
+import os
+
+
+from apscheduler.schedulers.background import BackgroundScheduler
+
+scheduler = BackgroundScheduler()
+
+TS_DIRECTORY = Path("/home/mia/101/static/stream")
+
+def clean_old_files():
+    ts_files = list(TS_DIRECTORY.glob("segment_*.ts"))
+    ts_files.sort(key=lambda f: f.stat().st_mtime)  # 按文件名排序,最旧的文件在前
+    if len(ts_files) > 20:
+        files_to_delete = ts_files[:len(ts_files) - 20]  # 超过 20 个的文件需要删除
+        for file in files_to_delete:
+            try:
+                os.remove(file)
+                print(f"Deleted old file: {file}")
+            except Exception as e:
+                print(f"Error deleting file {file}: {e}")
+
+# 添加定时任务
+scheduler.add_job(clean_old_files, 'interval', minutes=1)
+scheduler.start()
+
+@app.on_event("shutdown")
+def shutdown_event():
+    scheduler.shutdown()
 
 if __name__ == "__main__":
     uvicorn.run("main:app", host="0.0.0.0", port=9101, reload=False, log_config=None)