收起左侧

飞牛1.1.26 通过ffmpeg硬编解码qsv无论如何都报错 是系统还是我命令的问题?

0
回复
18
查看
[ 复制链接 ]

1

主题

0

回帖

0

牛值

江湖小虾

2026-3-27 21:01:22 显示全部楼层 阅读模式
硬解硬编都不行 只要开qsv就报错 只能CPU软编 一切显示正常 我用的命令是这个:
# 1. 先杀掉当前正在运行的慢转码进程
pkill -f auto_compress_h265.sh
sleep 1

# 2. 覆盖硬编优化版脚本(画质参数完全不变)
cat > /vol1/1000/auto_compress_h265.sh <<'EOF'
#!/bin/bash
# 飞牛OS Intel N150 xxh3-64去重版 | 硬编优先优化版 | 画质参数完全不变
# 核心规则:H265原文件完全不处理 | 转码成功直接替换 | 临时文件用完即删
# 画质保证:CRF=20 完全保留,软编参数和原脚本一致,仅优化硬编兼容性

# ===================== 可自定义配置项 =====================
SCAN_DIRS=(
  "/vol1/1000"
)
SCAN_RECURSIVE=true
THREADS_PER_TASK=4
CRF=20
# ==========================================================

# 基础配置
MIN_SIZE_M=1
MIN_SIZE_B=$((MIN_SIZE_M * 1024 * 1024))
LOW_BITRATE=500000
SCRIPT_PATH=$(readlink -f "$0")
LOG_FILE="${SCRIPT_PATH%.*}.log"
TMP_DIR="/vol1/1000/tmp"
TRANSCODE_MASTER="${TMP_DIR}/transcode_master.mp4"

# 依赖检查+自动创建临时目录
check_deps() {
  # 自动创建临时目录,不存在就建,权限正常
  mkdir -p "$TMP_DIR"
  chmod 755 "$TMP_DIR"

  # 检查必需依赖
  local deps=("ffprobe" "ffmpeg" "xxhsum")
  for dep in "${deps[@]}"; do
    if ! command -v "$dep" &>/dev/null; then
      echo "[$(date)] 错误:缺少必需依赖 $dep,请先安装" >> "$LOG_FILE"
      exit 1
    fi
  done
}

# 判断是否为H265/HEVC编码
is_h265_file() {
  local file="$1"
  local codec=$(ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)
  [[ "$codec" == "hevc" || "$codec" == "h265" ]]
}

# 正确提取xxh3-64哈希值
get_file_hash() {
  local file="$1"
  xxhsum -H3 "$file" 2>/dev/null | awk -F'=' '{print $2}' | tr -d ' '
}

# 转码母版函数(硬编优先优化版,画质参数完全不变)
transcode_to_master() {
  local source_file="$1"
  local master_file="$2"
  local tmp_master="${master_file}.tmp"

  echo "[$(date)] 开始转码母版文件:$source_file" >> "$LOG_FILE"

  # 读取视频参数
  local br=$(ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 "$source_file" 2>/dev/null || echo 0)
  local is_4k_hdr=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,color_transfer,color_space -of compact "$source_file" 2>/dev/null | grep -qE '3840|smpte2084|hlg|bt2020' && echo 1 || echo 0)

  # 色彩参数不变
  local csp_arg="-color_primaries bt709 -color_trc bt709 -colorspace bt709"
  [ "$is_4k_hdr" -eq 1 ] && csp_arg="-color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020"

  # ✅ 核心优化:硬编兼容性拉满,不强制解码器,避免非H264视频解码失败
  local common_args=(
    -hwaccel qsv
    -hwaccel_output_format nv12
    -i "$source_file"
    -map 0
    -c:a copy
    -c:s mov_text
    -movflags +faststart
  )

  # ✅ 硬编参数:CRF=20完全保留,和原脚本画质一致,preset适配QSV提速
  local qsv_vencode=(
    -c:v hevc_qsv
    -preset veryfast
    -crf "$CRF"
    -threads "$THREADS_PER_TASK"
    -vf "vpp_qsv=deinterlace=0"
  )

  # ✅ 软编fallback:完全和原脚本参数一致,画质压缩率丝毫不改
  local cpu_vencode=(
    -c:v libx265
    -preset fast
    -crf "$CRF"
    -threads "$THREADS_PER_TASK"
  )

  local transcode_success=0
  echo "[$(date)] 优先使用Intel QSV核显硬编" >> "$LOG_FILE"
  # 优先硬编
  if ffmpeg -y "${common_args[@]}" "${qsv_vencode[@]}" $csp_arg -f mp4 "$tmp_master" >> "$LOG_FILE" 2>&1; then
    transcode_success=1
    echo "[$(date)] QSV硬编成功" >> "$LOG_FILE"
  else
    rm -f "$tmp_master"
    echo "[$(date)] QSV硬编失败,切换原参数软编(画质完全不变)" >> "$LOG_FILE"
    # 硬编失败才fallback,软编参数和你原脚本100%一致
    if ffmpeg -y -i "$source_file" \
      -map 0 -c:a copy -c:s mov_text \
      "${cpu_vencode[@]}" \
      -movflags +faststart $csp_arg -f mp4 "$tmp_master" >> "$LOG_FILE" 2>&1; then
      transcode_success=1
    else
      rm -f "$tmp_master"
      echo "[$(date)] 母版转码失败,跳过整组文件:$source_file" >> "$LOG_FILE"
    fi
  fi

  if [ $transcode_success -eq 1 ]; then
    mv -f "$tmp_master" "$master_file"
    echo "[$(date)] 母版转码完成:$master_file" >> "$LOG_FILE"
    return 0
  else
    return 1
  fi
}

# 主程序
main() {
  check_deps
  echo "[$(date)] ========== 转码任务启动(硬编优先版,CRF=20画质不变)==========" >> "$LOG_FILE"

  # 扫描视频文件
  local find_args=(-type f \(
    -iname "*.mp4" -o -iname "*.mkv" -o -iname "*.ts" -o -iname "*.mov"
    -o -iname "*.avi" -o -iname "*.flv" -o -iname "*.wmv" -o -iname "*.m4v"
  \))

  local all_files=()
  for dir in "${SCAN_DIRS[@]}"; do
    if [ ! -d "$dir" ]; then
      echo "[$(date)] 警告:目录不存在,跳过:$dir" >> "$LOG_FILE"
      continue
    fi
    while IFS= read -r file; do
      local size=$(stat -c "%s" "$file" 2>/dev/null || echo 0)
      [ "$size" -ge "$MIN_SIZE_B" ] && all_files+=("$file")
    done < <(find "$dir" "${find_args[@]}" 2>/dev/null | sort)
  done

  if [ ${#all_files[@]} -eq 0 ]; then
    echo "[$(date)] 未找到符合条件的视频文件,任务结束" >> "$LOG_FILE"
    echo "[$(date)] ========== 任务完成 ==========" >> "$LOG_FILE"
    exit 0
  fi
  echo "[$(date)] 扫描完成,共找到 ${#all_files[@]} 个符合条件的视频文件" >> "$LOG_FILE"

  # 按Hash分组重复文件
  echo "[$(date)] 开始计算文件Hash,分组重复文件..." >> "$LOG_FILE"
  declare -A hash_file_map
  for file in "${all_files[@]}"; do
    hash=$(get_file_hash "$file")
    [ -n "$hash" ] && hash_file_map["$hash"]+="$file"$'\n'
  done

  local total_groups=${#hash_file_map[@]}
  local current_group=0
  echo "[$(date)] Hash分组完成,共 $total_groups 组独立视频文件" >> "$LOG_FILE"

  # 循环处理每组文件
  for hash in "${!hash_file_map[@]}"; do
    current_group=$((current_group + 1))
    mapfile -t file_list < <(echo -n "${hash_file_map[$hash]}" | grep -v '^$')
    local file_count=${#file_list[@]}

    echo "[$(date)] 正在处理第 $current_group/$total_groups 组,Hash:${hash:0:8}...,共 $file_count 个重复文件" >> "$LOG_FILE"

    # 本组有H265文件,直接跳过
    local has_h265=0
    for file in "${file_list[@]}"; do
      if is_h265_file "$file"; then
        has_h265=1
        break
      fi
    done
    if [ $has_h265 -eq 1 ]; then
      echo "[$(date)] 本组包含H265视频,整组跳过不处理" >> "$LOG_FILE"
      continue
    fi

    # 转码母版
    local source_file="${file_list[0]}"
    rm -f "$TRANSCODE_MASTER" "${TRANSCODE_MASTER}.tmp"

    if ! transcode_to_master "$source_file" "$TRANSCODE_MASTER"; then
      rm -f "$TRANSCODE_MASTER" "${TRANSCODE_MASTER}.tmp"
      continue
    fi

    # 批量替换本组所有文件
    echo "[$(date)] 开始替换本组所有 $file_count 个文件" >> "$LOG_FILE"
    for target_file in "${file_list[@]}"; do
      local out_file="${target_file%.*}.mp4"
      local tmp_out="${out_file}.tmp"

      if cp -f "$TRANSCODE_MASTER" "$tmp_out"; then
        rm -f "$target_file"
        mv -f "$tmp_out" "$out_file"
        echo "[$(date)] 替换完成:$out_file" >> "$LOG_FILE"
      else
        rm -f "$tmp_out"
        echo "[$(date)] 替换失败,原文件保持不变:$target_file" >> "$LOG_FILE"
      fi
    done

    # 本组处理完立刻清理临时文件
    rm -f "$TRANSCODE_MASTER" "${TRANSCODE_MASTER}.tmp"
    echo "[$(date)] 本组处理完成,临时文件已清理" >> "$LOG_FILE"
  done

  # 最终全局清理
  unset hash_file_map
  rm -f "$TRANSCODE_MASTER" "${TRANSCODE_MASTER}.tmp"
  echo "[$(date)] ========== 所有文件处理完成,临时文件已全部清理 ==========" >> "$LOG_FILE"
}

main "$@"
EOF

# 3. 赋权并后台启动
chmod +x /vol1/1000/auto_compress_h265.sh
nohup bash /vol1/1000/auto_compress_h265.sh > /dev/null 2>&1 &

# 4. 输出启动结果
echo "✅ 硬编优化版脚本已后台启动,进程号:$!"
echo "📊 查看实时日志命令:tail -f /vol1/1000/auto_compress_h265.log"
echo "🔍 验证硬编是否生效:日志中出现「QSV硬编成功」即为核显加速正常工作"
收藏
送赞
分享

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则