由于群晖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): $_"
}
}