diff --git a/.dockerignore b/.dockerignore index df67e1a..3477c81 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,24 +1,99 @@ -# Exclude common Python files and directories -venv/ -__pycache__/ -*.pyc -*.pyo -*.pyd -*.pyz -*.pyw -*.pyi -*.egg-info/ - -# Exclude development and local files -.env -.env.* -*.log -*.db - -# Exclude version control system files +# Git 相关 .git/ .gitignore +.gitattributes .svn/ -storage/ +# Python 相关 +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# 虚拟环境 +.env +.env.* +.venv +venv/ +ENV/ +env.bak/ +venv.bak/ + +# IDE 相关 +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# 操作系统相关 +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# 日志和数据库文件 +*.log +*.db +logs/ + +# 临时文件 +*.tmp +*.temp +temp/ +tmp/ + +# 存储目录(运行时生成的内容) +storage/temp/ +storage/tasks/ +storage/demo.py + +# 缓存目录 +.cache/ +.pytest_cache/ + +# 文档(保留必要的) +docs/ +*.md +!README.md + +# Docker 相关文件(避免递归复制) +Dockerfile.* +docker-compose.*.yml + +# 配置文件(使用示例配置) config.toml + +# 资源文件中的大文件 +resource/videos/ +resource/songs/ + +# 测试文件 +tests/ +test_* +*_test.py + +# 其他不必要的文件 +*.bak +*.orig +*.rej diff --git a/Dockerfile b/Dockerfile index a23cf59..ee70617 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,63 +1,97 @@ -# 构建阶段 -FROM python:3.10-slim-bullseye as builder +# 多阶段构建 - 构建阶段 +FROM python:3.12-slim-bookworm AS builder + +# 设置构建参数 +ARG DEBIAN_FRONTEND=noninteractive # 设置工作目录 WORKDIR /build # 安装构建依赖 -RUN apt-get update && apt-get install -y \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ git \ git-lfs \ + pkg-config \ && rm -rf /var/lib/apt/lists/* -# 创建虚拟环境 -RUN python -m venv /opt/venv +# 升级 pip 并创建虚拟环境 +RUN python -m pip install --upgrade pip setuptools wheel && \ + python -m venv /opt/venv + +# 激活虚拟环境 ENV PATH="/opt/venv/bin:$PATH" -# 首先安装 PyTorch(因为它是最大的依赖) -RUN pip install --no-cache-dir torch torchvision torchaudio - -# 然后安装其他依赖 +# 复制 requirements.txt 并安装 Python 依赖 COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir --upgrade pip && \ + pip install --no-cache-dir -r requirements.txt # 运行阶段 -FROM python:3.10-slim-bullseye +FROM python:3.12-slim-bookworm + +# 设置运行参数 +ARG DEBIAN_FRONTEND=noninteractive # 设置工作目录 WORKDIR /NarratoAI -# 从builder阶段复制虚拟环境 +# 从构建阶段复制虚拟环境 COPY --from=builder /opt/venv /opt/venv -ENV PATH="/opt/venv/bin:$PATH" -# 安装运行时依赖 -RUN apt-get update && apt-get install -y \ +# 设置环境变量 +ENV PATH="/opt/venv/bin:$PATH" \ + PYTHONPATH="/NarratoAI" \ + PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PYTHONIOENCODING=utf-8 \ + LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 + +# 安装运行时系统依赖 +RUN apt-get update && apt-get install -y --no-install-recommends \ imagemagick \ ffmpeg \ wget \ + curl \ git-lfs \ - && rm -rf /var/lib/apt/lists/* \ - && sed -i '/ /dev/null; then + log_error "Docker 未安装,请先安装 Docker" + exit 1 + fi + + if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then + log_error "Docker Compose 未安装,请先安装 Docker Compose" + exit 1 + fi + + if ! docker info &> /dev/null; then + log_error "Docker 服务未运行,请启动 Docker" + exit 1 + fi +} + +# 检查配置文件 +check_config() { + if [ ! -f "config.toml" ]; then + if [ -f "config.example.toml" ]; then + log_warning "config.toml 不存在,复制示例配置文件" + cp config.example.toml config.toml + log_info "请编辑 config.toml 文件配置您的 API 密钥" + else + log_error "未找到配置文件模板" + exit 1 + fi + fi +} + +# 构建镜像 +build_image() { + log_info "构建 Docker 镜像..." + + local build_args="" + if [ "$NO_CACHE" = "true" ]; then + build_args="--no-cache" + fi + + docker-compose build $build_args +} + +# 启动服务 +start_services() { + log_info "启动 NarratoAI 服务..." + + docker-compose down 2>/dev/null || true + docker-compose up -d +} + +# 等待服务就绪 +wait_for_service() { + log_info "等待服务就绪..." + + local max_attempts=30 + local attempt=1 + + while [ $attempt -le $max_attempts ]; do + if curl -f http://localhost:8501/_stcore/health &>/dev/null; then + log_info "服务已就绪" + return 0 + fi + + sleep 2 + ((attempt++)) + done + + log_warning "服务启动超时,请检查日志" + return 1 +} + +# 显示部署信息 +show_deployment_info() { + echo + log_info "NarratoAI 部署完成!" + echo "访问地址: http://localhost:8501" + echo + echo "常用命令:" + echo " 查看日志: docker-compose logs -f" + echo " 停止服务: docker-compose down" + echo " 重启服务: docker-compose restart" +} + +# 主函数 +main() { + FORCE_BUILD=false + NO_CACHE=false + + # 解析命令行参数 + while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + -b|--build) + FORCE_BUILD=true + shift + ;; + --no-cache) + NO_CACHE=true + shift + ;; + *) + log_error "未知选项: $1" + show_help + exit 1 + ;; + esac + done + + # 执行部署流程 + log_info "开始 NarratoAI Docker 部署..." + + check_requirements + check_config + + if [ "$FORCE_BUILD" = "true" ] || ! docker images | grep -q "narratoai"; then + build_image + fi + + start_services + + if wait_for_service; then + show_deployment_info + else + log_error "部署失败,请检查日志" + docker-compose logs --tail=20 + exit 1 + fi +} + +# 执行主函数 +main "$@" diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index c4ca7d3..87e5ff4 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,8 +1,87 @@ #!/bin/bash set -e -if [ "$1" = "webui" ]; then - exec streamlit run webui.py --browser.serverAddress=127.0.0.1 --server.enableCORS=True --browser.gatherUsageStats=False -else - exec "$@" -fi \ No newline at end of file +# 函数:打印日志 +log() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" +} + +# 函数:检查必要的文件和目录 +check_requirements() { + log "检查应用环境..." + + # 检查配置文件 + if [ ! -f "config.toml" ]; then + if [ -f "config.example.toml" ]; then + log "复制示例配置文件..." + cp config.example.toml config.toml + else + log "警告: 未找到配置文件" + fi + fi + + # 检查必要的目录 + for dir in "storage/temp" "storage/tasks" "storage/json" "storage/narration_scripts" "storage/drama_analysis"; do + if [ ! -d "$dir" ]; then + log "创建目录: $dir" + mkdir -p "$dir" + fi + done + + log "环境检查完成" +} + +# 函数:启动 WebUI +start_webui() { + log "启动 NarratoAI WebUI..." + + # 检查端口是否可用 + if command -v netstat >/dev/null 2>&1; then + if netstat -tuln | grep -q ":8501 "; then + log "警告: 端口 8501 已被占用" + fi + fi + + # 启动 Streamlit 应用 + exec streamlit run webui.py \ + --server.address=0.0.0.0 \ + --server.port=8501 \ + --server.enableCORS=true \ + --server.maxUploadSize=2048 \ + --server.enableXsrfProtection=false \ + --browser.gatherUsageStats=false \ + --browser.serverAddress=0.0.0.0 \ + --logger.level=info +} + +# 主逻辑 +log "NarratoAI Docker 容器启动中..." + +# 检查环境 +check_requirements + +# 根据参数执行不同的命令 +case "$1" in + "webui"|"") + start_webui + ;; + "bash"|"sh") + log "启动交互式 shell..." + exec /bin/bash + ;; + "health") + # 健康检查命令 + log "执行健康检查..." + if curl -f http://localhost:8501/_stcore/health >/dev/null 2>&1; then + log "健康检查通过" + exit 0 + else + log "健康检查失败" + exit 1 + fi + ;; + *) + log "执行自定义命令: $*" + exec "$@" + ;; +esac \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 6465e53..b9bda86 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,45 +1,35 @@ -# 必须项 -requests~=2.32.0 +# 核心依赖 +requests>=2.32.0 moviepy==2.1.1 edge-tts==6.1.19 -streamlit~=1.45.0 +streamlit>=1.45.0 watchdog==6.0.0 -loguru~=0.7.3 -tomli~=2.2.1 +loguru>=0.7.3 +tomli>=2.2.1 +tomli-w>=1.0.0 pydub==0.25.1 pysrt==1.1.2 -openai~=1.77.0 +# AI 服务依赖 +openai>=1.77.0 google-generativeai>=0.8.5 -azure-cognitiveservices-speech~=1.37.0 +azure-cognitiveservices-speech>=1.37.0 -# 待优化项 -# opencv-python==4.11.0.86 -# scikit-learn==1.6.1 +# 图像处理依赖 +Pillow>=10.3.0 +# 进度条和重试机制 +tqdm>=4.66.6 +tenacity>=9.0.0 +# 可选依赖(根据功能需要) +# 如果需要本地语音识别,取消注释下面的行 +# faster-whisper>=1.0.1 -# faster-whisper~=1.0.1 -# tomli~=2.0.1 -# aiohttp~=3.10.10 -# httpx==0.27.2 -# urllib3~=2.2.1 +# 如果需要 OpenCV 图像处理,取消注释下面的行 +# opencv-python>=4.11.0.86 -# python-multipart~=0.0.9 -# redis==5.0.3 -# opencv-python~=4.10.0.84 -# git-changelog~=2.5.2 -# watchdog==5.0.2 -# pydub==0.25.1 -# psutil>=5.9.0 -# scikit-learn~=1.5.2 -# pillow==10.3.0 -# python-dotenv~=1.0.1 - -# tqdm>=4.66.6 -# tenacity>=9.0.0 -# tiktoken==0.8.0 -# pysrt==1.1.2 -# transformers==4.50.0 - -# yt-dlp==2025.4.30 \ No newline at end of file +# 如果需要 CUDA 支持,取消注释下面的行 +# torch>=2.0.0 +# torchvision>=0.15.0 +# torchaudio>=2.0.0 \ No newline at end of file