使用FFmpeg和Intel QSV将蓝光原盘转码为HEVC格式以适应网络播放

由于群晖NAS不再支持Video Station,因此决定将NAS上的蓝光原盘视频转码为适合网络播放的低码率格式。在综合考虑质量和转码速度后,最终选择使用FFmpeg配合Intel Quick Sync Video (QSV)将视频转码为H.265 (HEVC) Main10格式。

本文为个人笔记,内容简洁,不讨论选择背后的原因。

硬件配置需求

该方案至少需要Kaby Lake(7代Intel® Core™)或更新版本的带核显Intel处理器,或Intel® Arc™独立显卡,以便支持QSV硬件加速。

视频格式情况

收藏的蓝光原盘视频几乎均为NTSC格式,按以下三种情况处理:

  • 逐行扫描:常见为24p或30p,帧率为24000/1001或30000/1001,此类视频无需额外处理。
  • 隔行扫描:常见为30i,帧率为30000/1001,此类视频需要反交错处理。
  • 24p插帧:视频为30i或30p,帧率为30000/1001,此类视频需进行Inverse Telecine (IVTC)或帧率转换。

使用vpp_qsv可以智能地选择适当的反交错算法和帧率转换方法,因此无需手动指定处理方式。

音频处理

对于流媒体播放的音频部分,使用AAC 48000Hz 256Kbps编码已足够,原盘中如有96000Hz或其他格式的音频,也统一转换为48000Hz处理。由于本人收藏的蓝光原盘主要为电视动画,这里不考虑多音轨的情况。

Powershell代码

# 添加 FFmpeg 到 PATH
$env:PATH += ";$env:PUBLIC\ffmpeg-7.1-full_build\bin"

# 视频输入参数
$VideoInputParams = @(
    '-init_hw_device', 'qsv:hw,child_device_type=d3d11va',
    '-hwaccel', 'qsv',
    '-hwaccel_output_format', 'qsv',
    '-c:v', 'h264_qsv'
)

# 视频输出参数
$VideoOutputParams = @(
    '-c:v', 'hevc_qsv',
    '-global_quality', '25',
    '-extbrc', '1',
    '-b_strategy', '1',
    '-bf', '7',
    '-refs', '4',
    '-g', '256',
    '-fps_mode', 'passthrough'
)

# 音频输出参数
$AudioOutputParams = @('-b:a', '256k')

# 音频滤镜
$AudioFilters = @('-af', 'aresample=resampler=soxr:precision=28:out_sample_rate=48000')

# 选择模式
Switch (Read-Host "1. HD to HEVC.`n2. HD to HEVC with Deinterlace.`n3. HD to HEVC with IVTC.`n4. HD to HEVC with Audio SRC.`n5. HD to HEVC with Deinterlace & Audio SRC.`n6. HD to HEVC with IVTC & Audio SRC.`n`n`tPlease select a mode") {
    1 { $VideoFilters = @('-vf', 'vpp_qsv=format=p010le') }
    2 { $VideoFilters = @('-vf', 'vpp_qsv=format=p010le:deinterlace=2') }
    3 { $VideoFilters = @('-vf', 'vpp_qsv=format=p010le:deinterlace=2:framerate=24000/1001') }
    4 { $VideoFilters = @('-vf', 'vpp_qsv=format=p010le'); $UseAudioFilters = $true }
    5 { $VideoFilters = @('-vf', 'vpp_qsv=format=p010le:deinterlace=2'); $UseAudioFilters = $true }
    6 { $VideoFilters = @('-vf', 'vpp_qsv=format=p010le:deinterlace=2:framerate=24000/1001'); $UseAudioFilters = $true }
}

# 处理视频文件
Get-ChildItem *.m2ts, *.mkv, *.mov | ForEach-Object {
    $params = $VideoInputParams + '-i' + $_.FullName + $VideoFilters + $VideoOutputParams

    if ($UseAudioFilters) {
        $params += $AudioFilters
    }
    
    $params += $AudioOutputParams

    # 执行 FFmpeg
    try {
        ffmpeg.exe $params -y "$($_.BaseName).mp4"
    } catch {
        Write-Host "Error processing $($_.Name): $_"
    }
}

评论

发表评论