|
@@ -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)
|