safesight-edge/scripts/systemd/install.sh
2026-02-25 12:37:08 +08:00

272 lines
9.8 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# RK3588 Media Server Systemd 安装脚本
# 适用于 Orange Pi 5 Plus (RK3588)
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ RK3588 Media Server Systemd 安装脚本 ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════╝${NC}"
echo ""
# 检查 root 权限
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}错误: 请使用 sudo 运行此脚本${NC}"
exit 1
fi
# 确定项目目录
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
BUILD_DIR="$PROJECT_DIR/build"
INSTALL_DIR="/opt/rk3588-media-server"
SERVICE_DIR="/etc/systemd/system"
echo "项目目录: $PROJECT_DIR"
echo "安装目录: $INSTALL_DIR"
echo ""
# 检查编译产物
if [ ! -f "$BUILD_DIR/media-server" ]; then
echo -e "${RED}错误: 未找到编译好的 media-server${NC}"
echo "请先编译项目:"
echo " cd $PROJECT_DIR"
echo " cmake -S . -B build -DCMAKE_BUILD_TYPE=Release ..."
echo " cmake --build build -j\$(nproc)"
exit 1
fi
# 检查插件
if [ ! -d "$BUILD_DIR/plugins" ] || [ -z "$(ls -A $BUILD_DIR/plugins/*.so 2>/dev/null)" ]; then
echo -e "${YELLOW}警告: 未找到插件目录或插件为空${NC}"
echo "请确保编译了插件: cmake --build build -j\$(nproc)"
read -p "是否继续? (y/N): " -n 1 -r
echo
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
fi
echo -e "${GREEN}${NC} 编译产物检查通过"
echo ""
# 选择配置文件
echo "请选择配置文件:"
echo ""
echo " 1) test_cam1_face_det_rtsp_server.json (推荐 - 简单稳定无gate问题)"
echo " 2) sample_cam1_native_rtsp_face.json (完整功能 - YOLO+人脸检测+识别)"
echo " 3) test_cam1_face_det_recog_rtsp_server.json (人脸识别)"
echo " 4) sample_cam1.json (完整功能 - 需要手动禁用gate_face_cam1)"
echo ""
read -p "请输入选项 [1-4默认1]: " choice
choice=${choice:-1}
case $choice in
1)
CONFIG_FILE="$PROJECT_DIR/configs/test_cam1_face_det_rtsp_server.json"
CONFIG_DESC="test_cam1_face_det_rtsp_server.json (简单稳定)"
;;
2)
CONFIG_FILE="$PROJECT_DIR/configs/sample_cam1_native_rtsp_face.json"
CONFIG_DESC="sample_cam1_native_rtsp_face.json (完整功能)"
;;
3)
CONFIG_FILE="$PROJECT_DIR/configs/test_cam1_face_det_recog_rtsp_server.json"
CONFIG_DESC="test_cam1_face_det_recog_rtsp_server.json (人脸识别)"
;;
4)
CONFIG_FILE="$PROJECT_DIR/configs/sample_cam1.json"
CONFIG_DESC="sample_cam1.json (完整功能,需手动修复)"
;;
*)
echo "无效选项,使用默认配置"
CONFIG_FILE="$PROJECT_DIR/configs/test_cam1_face_det_rtsp_server.json"
CONFIG_DESC="test_cam1_face_det_rtsp_server.json (默认)"
;;
esac
echo ""
echo -e "选择配置: ${GREEN}$CONFIG_DESC${NC}"
echo ""
# 开始安装
echo -e "${YELLOW}[1/6] 创建安装目录...${NC}"
mkdir -p "$INSTALL_DIR"/{bin/plugins,lib,etc,logs,models,web/hls}
echo -e "${GREEN}${NC} 目录创建完成"
echo -e "${YELLOW}[2/6] 复制主程序和插件...${NC}"
cp "$BUILD_DIR/media-server" "$INSTALL_DIR/bin/"
chmod +x "$INSTALL_DIR/bin/media-server"
# 复制插件
if [ -d "$BUILD_DIR/plugins" ]; then
cp "$BUILD_DIR"/plugins/*.so "$INSTALL_DIR/bin/plugins/" 2>/dev/null || true
echo -e "${GREEN}${NC} 插件复制完成 ($(ls $INSTALL_DIR/bin/plugins/*.so 2>/dev/null | wc -l) 个)"
else
echo -e "${YELLOW}⚠ 未找到插件目录${NC}"
fi
# 复制依赖库
if ls "$BUILD_DIR"/*.so 1> /dev/null 2>&1; then
cp "$BUILD_DIR"/*.so "$INSTALL_DIR/lib/" 2>/dev/null || true
echo -e "${GREEN}${NC} 依赖库复制完成"
fi
echo -e "${YELLOW}[3/6] 复制模型文件...${NC}"
# 复制第三方模型
if [ -d "$PROJECT_DIR/third_party/rknpu2/examples/rknn_yolov5_demo/model/RK3588" ]; then
mkdir -p "$INSTALL_DIR/models"
cp "$PROJECT_DIR/third_party/rknpu2/examples/rknn_yolov5_demo/model/RK3588"/*.rknn "$INSTALL_DIR/models/" 2>/dev/null || true
fi
# 复制项目模型目录
if [ -d "$PROJECT_DIR/models" ]; then
cp -r "$PROJECT_DIR/models"/* "$INSTALL_DIR/models/" 2>/dev/null || true
fi
echo -e "${GREEN}${NC} 模型文件复制完成"
echo -e "${YELLOW}[4/6] 处理配置文件...${NC}"
# 复制并修复配置
cp "$CONFIG_FILE" "$INSTALL_DIR/etc/media-server.json"
# 使用 Python 修复配置文件中的路径
python3 << EOF
import json
import os
config_file = "$INSTALL_DIR/etc/media-server.json"
install_dir = "$INSTALL_DIR"
project_dir = "$PROJECT_DIR"
def fix_path(path):
if not path or not isinstance(path, str):
return path
if path.startswith('./'):
# web/ 路径指向安装目录
if path.startswith('./web/'):
return os.path.join(install_dir, path[2:])
# models/ 路径指向安装目录
elif path.startswith('./models/'):
return os.path.join(install_dir, path[2:])
# 其他路径,优先相对于项目目录查找,否则安装目录
else:
abs_path = os.path.join(project_dir, path)
if os.path.exists(abs_path):
return abs_path
return os.path.join(install_dir, path[2:])
return path
try:
with open(config_file, 'r') as f:
config = json.load(f)
# 修复 sample_cam1.json 中的 gate_face_cam1 问题
for graph in config.get('graphs', []):
nodes = graph.get('nodes', [])
edges = graph.get('edges', [])
# 找到所有节点ID
node_ids = {node['id'] for node in nodes}
# 找到有输入边的节点
nodes_with_input = set()
for edge in edges:
if isinstance(edge, list) and len(edge) >= 2:
nodes_with_input.add(edge[1])
# 禁用没有输入的 filter/sink 节点
for node in nodes:
if node.get('role') in ['filter', 'sink'] and node['id'] not in nodes_with_input:
if node.get('enable', True):
print(f"禁用无输入节点: {node['id']} (role={node.get('role')})")
node['enable'] = False
# 修复所有路径
for node in nodes:
if 'model_path' in node:
old = node['model_path']
node['model_path'] = fix_path(old)
if old != node['model_path']:
print(f"修复路径: {old} -> {node['model_path']}")
if 'gallery' in node and 'path' in node['gallery']:
old = node['gallery']['path']
node['gallery']['path'] = fix_path(old)
if old != node['gallery']['path']:
print(f"修复路径: {old} -> {node['gallery']['path']}")
if 'outputs' in node:
for output in node['outputs']:
if 'path' in output:
old = output['path']
output['path'] = fix_path(old)
if old != output['path']:
print(f"修复路径: {old} -> {output['path']}")
with open(config_file, 'w') as f:
json.dump(config, f, indent=2)
print("配置文件处理完成")
except Exception as e:
print(f"处理配置文件时出错: {e}")
# 保留原始文件
EOF
echo -e "${GREEN}${NC} 配置文件处理完成"
echo " 配置文件: $INSTALL_DIR/etc/media-server.json"
echo ""
echo -e "${YELLOW}[5/6] 安装 Systemd 服务...${NC}"
cp "$SCRIPT_DIR/media-server.service" "$SERVICE_DIR/"
# 重新加载 systemd
systemctl daemon-reload
systemctl enable media-server
echo -e "${GREEN}${NC} Systemd 服务安装完成"
echo -e "${YELLOW}[6/6] 验证安装...${NC}"
echo ""
echo "安装内容:"
echo " 主程序: $(ls -lh $INSTALL_DIR/bin/media-server | awk '{print $5, $9}')"
echo " 插件数: $(ls $INSTALL_DIR/bin/plugins/*.so 2>/dev/null | wc -l)"
echo " 模型数: $(ls $INSTALL_DIR/models/*.rknn 2>/dev/null | wc -l)"
echo " 配置: $INSTALL_DIR/etc/media-server.json"
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ 安装完成! ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo "管理命令:"
echo " 启动: sudo systemctl start media-server"
echo " 停止: sudo systemctl stop media-server"
echo " 状态: sudo systemctl status media-server"
echo " 日志: sudo journalctl -u media-server -f"
echo ""
echo "重要提示:"
echo " 1. 编辑配置修改RTSP源地址:"
echo " sudo nano $INSTALL_DIR/etc/media-server.json"
echo ""
echo " 2. 确保模型文件存在:"
echo " ls $INSTALL_DIR/models/"
echo ""
echo " 3. 首次启动前检查RTSP源是否可访问"
echo ""
read -p "是否立即启动服务? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
systemctl start media-server
sleep 2
if systemctl is-active --quiet media-server; then
echo -e "${GREEN}${NC} 服务启动成功!"
systemctl status media-server --no-pager
else
echo -e "${RED}${NC} 服务启动失败,查看日志:"
echo " sudo journalctl -u media-server -n 20"
fi
fi