侧边栏壁纸
博主头像
龍騰博客 博主等级

行动起来,活在当下

  • 累计撰写 170 篇文章
  • 累计创建 31 个标签
  • 累计收到 7 条评论

目 录CONTENT

文章目录

长音频分段处理 + 内存限额方案

管理员
2026-08-03 / 0 评论 / 0 点赞 / 0 阅读 / 0 字

配合之前的 whisper.cpp Vulkan 部署指南使用,解决长录音(会议、课程)导致的内存占用问题,避免跟 Qwen3.6-35B 抢内存触发 OOM。

第一步:docker-compose.yml 加内存限额

在原来的基础上加 deploy.resources.limits,给 whisper-server 设个硬顶,防止它把内存占爆:

services:
  whisper-server:
    image: ghcr.io/ggerganov/whisper.cpp:main-vulkan
    container_name: whisper-server
    restart: unless-stopped
    ports:
      - "8090:8080"
    volumes:
      - ./models:/models
    devices:
      - /dev/dri:/dev/dri
    deploy:
      resources:
        limits:
          memory: 6G        # 按需调整,48G总内存里给whisper留个上限
        reservations:
          memory: 2G
    command: >
      --model /models/ggml-large-v3-turbo.bin
      --host 0.0.0.0
      --port 8080
      --language zh
      --print-progress

注意:如果你是用 docker compose up 而不是 swarm 模式,deploy.resources 在部分 Compose 版本下不生效,稳妥起见换成经典写法:

    mem_limit: 6g
    memswap_limit: 6g

两种写法效果类似,用后者兼容性更好。

第二步:长音频自动分段脚本

超过设定时长的音频,先用 ffmpeg 切片,分段调用 API,最后把文字结果拼接起来。避免整个超长文件一次性塞进模型。

#!/bin/bash
# whisper-long-audio.sh
# 用法: ./whisper-long-audio.sh <音频文件> [分段时长秒数,默认600]

set -e

INPUT_FILE="$1"
SEGMENT_SECONDS="${2:-600}"   # 默认每段10分钟
WHISPER_API="http://192.168.0.188:8090/v1/audio/transcriptions"
WORK_DIR=$(mktemp -d)
OUTPUT_FILE="${INPUT_FILE%.*}_transcript.txt"

if [ -z "$INPUT_FILE" ]; then
  echo "用法: $0 <音频文件> [分段时长秒数]"
  exit 1
fi

echo "临时目录: $WORK_DIR"
echo "开始切分音频,每段 ${SEGMENT_SECONDS} 秒..."

# 用 ffmpeg 按时长切片,输出统一转成 16kHz 单声道 wav
ffmpeg -i "$INPUT_FILE" -f segment -segment_time "$SEGMENT_SECONDS" \
  -ar 16000 -ac 1 -c:a pcm_s16le \
  "$WORK_DIR/segment_%03d.wav" -y -loglevel error

echo "切分完成,开始逐段识别..."
> "$OUTPUT_FILE"

for segment in "$WORK_DIR"/segment_*.wav; do
  echo "处理: $(basename "$segment")"
  result=$(curl -s "$WHISPER_API" \
    -F file="@$segment" \
    -F language="zh")

  # 提取文本字段(假设返回JSON里有text字段,具体按whisper-server实际返回格式调整)
  text=$(echo "$result" | grep -o '"text":"[^"]*"' | sed 's/"text":"//;s/"$//')
  echo "$text" >> "$OUTPUT_FILE"
  echo "" >> "$OUTPUT_FILE"

  # 每段之间留点间隔,给内存回收和GPU降温的时间,
  # 也顺带避开和LLM推理请求撞车的高峰
  sleep 2
done

echo "全部完成,结果保存在: $OUTPUT_FILE"
rm -rf "$WORK_DIR"

保存后:

chmod +x whisper-long-audio.sh
./whisper-long-audio.sh /path/to/meeting.mp3 600

第三步:反代 body size 限制

如果你前面套了 Nginx(fnOS 常见做法),记得加大上传限制,否则大文件还没到 whisper-server 就被拦下了:

location /whisper/ {
    proxy_pass http://192.168.0.188:8090/;
    client_max_body_size 500M;
    proxy_read_timeout 600s;   # 长音频转写时间长,超时也要放宽
}

小结:为什么这样能避免 OOM

  1. 切片:把内存占用从"整段音频总时长线性增长"变成"单段固定上限",每次只处理10分钟的量,处理完释放,不会累积。

  2. mem_limit 硬顶:即使某次异常导致占用飙升,也不会波及到跟它同机运行的 Qwen3.6-35B 或 Frigate/CompreFace,容器会先被 OOM killer 干掉,而不是拖垮整个系统。

  3. 请求间隔:段与段之间加了 sleep,给 GPU/内存喘口气的时间,也降低了和 LLM 并发请求抢资源的概率。

如果你想要更进一步,比如自动检测音频总时长决定要不要走分段逻辑(短音频直接一次性处理,省得切片浪费时间),跟我说一声,我再加个判断逻辑进去。

0

评论区