Files
python----/audio_recorder.py
admin 2d8c1ea8f9 chore: 批量新增各类工具脚本与配置文件
1. 新增音频录制、下载、上传相关脚本
2. 新增数据库操作、API调用工具
3. 新增Excel数据处理脚本
4. 新增弱密码检测脚本
2026-06-14 17:47:15 +08:00

222 lines
7.8 KiB
Python

from flask import Flask, jsonify, request
import subprocess
import threading
import time
import os
from datetime import datetime
import schedule
app = Flask(__name__)
# 配置参数
RTSP_URL = "rtsp://10.68.66.174/audio"
RECORD_DURATION_MINUTES = 60 # 录制时长(分钟)
REST_DURATION_MINUTES = 20 # 休息时长(分钟)
START_HOUR = 8 # 开始时间(小时)
END_HOUR = 20 # 结束时间(小时)
OUTPUT_DIR = "./" # 输出目录
# 录制状态
recording_state = {
"is_recording": False,
"current_file": None,
"start_time": None,
"total_recorded": 0,
"schedule_next": None
}
def get_output_path():
"""生成带时间戳的文件名"""
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
return os.path.join(OUTPUT_DIR, f"rtsp_{timestamp}.wav")
def is_within_schedule():
"""检查当前是否在有效时间段内"""
current_hour = datetime.now().hour
return START_HOUR <= current_hour < END_HOUR
def record_audio():
"""执行音频录制"""
if recording_state["is_recording"]:
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 正在录制中,跳过本次录制")
return
if not is_within_schedule():
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 不在有效时间段内(8:00-20:00),跳过本次录制")
return
output_file = get_output_path()
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 开始录制: {output_file}")
recording_state["is_recording"] = True
recording_state["current_file"] = output_file
recording_state["start_time"] = datetime.now()
try:
# 使用 ffmpeg 录制
cmd = [
'ffmpeg',
'-rtsp_transport', 'tcp',
'-i', RTSP_URL,
'-t', str(RECORD_DURATION_MINUTES * 60),
'-acodec', 'pcm_s16le',
'-ar', '16000',
'-ac', '1',
'-y',
output_file
]
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True
)
# 监控录制进度
start_time = time.time()
while process.poll() is None:
if os.path.exists(output_file):
size_mb = os.path.getsize(output_file) / (1024 * 1024)
elapsed = time.time() - start_time
print(f"\r进度: {int(elapsed)}秒 / {RECORD_DURATION_MINUTES * 60}秒, 大小: {size_mb:.2f}MB", end='')
time.sleep(1)
print() # 换行
# 录制完成
if os.path.exists(output_file):
size_mb = os.path.getsize(output_file) / (1024 * 1024)
recording_state["total_recorded"] += 1
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 录制完成: {output_file} ({size_mb:.2f}MB)")
else:
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 录制失败")
except Exception as e:
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 录制错误: {e}")
finally:
recording_state["is_recording"] = False
recording_state["current_file"] = None
recording_state["start_time"] = None
# 录制完成后,在有效时间段内等待 REST_DURATION_MINUTES 分钟
if is_within_schedule():
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 进入休息模式,等待 {REST_DURATION_MINUTES} 分钟...")
time.sleep(REST_DURATION_MINUTES * 60)
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 休息结束")
else:
# 不在有效时间段,等待到下一个有效时间段
now = datetime.now()
if now.hour >= END_HOUR:
# 等待到明天早上 8 点
from datetime import timedelta
next_day = now + timedelta(days=1)
target = next_day.replace(hour=START_HOUR, minute=0, second=0, microsecond=0)
else:
# 等待到今天早上 8 点
target = now.replace(hour=START_HOUR, minute=0, second=0, microsecond=0)
wait_seconds = (target - now).total_seconds()
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 不在有效时间段,等待 {wait_seconds/3600:.1f} 小时...")
time.sleep(wait_seconds)
def schedule_recording():
"""定时录制任务"""
thread = threading.Thread(target=record_audio, daemon=True)
thread.start()
def run_scheduler():
"""运行定时器"""
# 设置定时任务:每小时整点录制
schedule.every().hour.at(":00").do(schedule_recording)
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 定时录制服务已启动")
print(f" - 录制时长: {RECORD_DURATION_MINUTES} 分钟")
print(f" - 休息时长: {REST_DURATION_MINUTES} 分钟")
print(f" - 有效时段: {START_HOUR}:00 - {END_HOUR}:00")
print("-" * 50)
while True:
schedule.run_pending()
time.sleep(1)
# Flask 路由
@app.route('/')
def index():
"""主页"""
return jsonify({
"service": "RTSP Audio Recorder",
"status": "running" if recording_state["is_recording"] else "idle",
"config": {
"rtsp_url": RTSP_URL,
"record_duration": f"{RECORD_DURATION_MINUTES} minutes",
"rest_duration": f"{REST_DURATION_MINUTES} minutes",
"schedule": f"{START_HOUR}:00 - {END_HOUR}:00"
}
})
@app.route('/status')
def status():
"""获取录制状态"""
return jsonify({
"is_recording": recording_state["is_recording"],
"current_file": recording_state["current_file"],
"start_time": recording_state["start_time"].isoformat() if recording_state["start_time"] else None,
"total_recorded": recording_state["total_recorded"],
"current_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
"is_in_schedule": is_within_schedule()
})
@app.route('/start')
def start_recording():
"""手动开始录制"""
if recording_state["is_recording"]:
return jsonify({"status": "error", "message": "正在录制中"})
thread = threading.Thread(target=record_audio, daemon=True)
thread.start()
return jsonify({"status": "success", "message": "开始录制"})
@app.route('/stop')
def stop_recording():
"""手动停止录制(终止 ffmpeg 进程)"""
if not recording_state["is_recording"]:
return jsonify({"status": "error", "message": "当前没有在录制"})
# 查找并终止 ffmpeg 进程
try:
subprocess.run(['taskkill', '/f', '/im', 'ffmpeg.exe'], capture_output=True)
recording_state["is_recording"] = False
return jsonify({"status": "success", "message": "已停止录制"})
except Exception as e:
return jsonify({"status": "error", "message": str(e)})
@app.route('/files')
def list_files():
"""列出已录制的文件"""
files = []
for f in os.listdir(OUTPUT_DIR):
if f.endswith('.wav') and f.startswith('rtsp_'):
path = os.path.join(OUTPUT_DIR, f)
files.append({
"name": f,
"size": os.path.getsize(path),
"modified": datetime.fromtimestamp(os.path.getmtime(path)).isoformat()
})
return jsonify({"files": files})
if __name__ == '__main__':
# 确保输出目录存在
os.makedirs(OUTPUT_DIR, exist_ok=True)
# 启动定时器线程
scheduler_thread = threading.Thread(target=run_scheduler, daemon=True)
scheduler_thread.start()
# 启动 Flask 服务
print(f"\n{'='*50}")
print(f"RTSP 音频录制服务")
print(f"{'='*50}")
app.run(host='0.0.0.0', port=5000, debug=False, use_reloader=False)