电影是由多个“图片”连续播放组成的,每个“图片”被称为帧,电影单位时间内播放的帧的数目称为帧率,常见帧率数值有:23.97、24、29.97等等
相邻连续帧主要部分基本相同,画面中只有部分内容发生运动改变,因此可以对于相似帧只保存变换的内容,用于储存节约空间。
根据帧储存性质,可以分为3类:
I帧(Intracoded帧):此帧是一个独立的帧,它不使用其前后的帧中的任何信息。一般作为参考帧的基础架构,储存完整的帧信息,占用空间较大。
P帧(Predicted帧):P帧又称帧间预测编码帧,需要参考前面的I帧才能进行编码。表示的是当前帧画面与前一帧(前一帧可能是I帧也可能是P帧)的差别。解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。与I帧相比,P帧通常占用更少的空间。
B帧(Bi-predictive帧):B帧又称双向预测编码帧,也就是B帧记录的是本帧与前后帧的差别。也就是说要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是对解码性能要求较高。
不同编码根据自己算法,对于一个视频进行压缩编码,不同的编码方式,对于不同帧处理方式不同,有着自己的标准。
源:源是指高质量可以用于进行压制编码的视频,一般包括蓝光圆盘、高质量的Web(一般4K的SDR)等。压片时应采用最优质的源进行压制,提高压制质量。
随着很多老片的BD推出,很多蓝光源是从低分辨率拉到高分辨率,被称为(---),在压制时应注意复原为原版的分辨率,不要压制过高的分辨率。关于WEB源应谨慎使用,尤其1080p的web-dl一般都为低质量不可以进行二次压制源,如非必要请勿压制,4k的SDR web源目前评价较好,往往好于1080p的BD来源,对于压制1080p的视频可以进行比较使用。
!!!对于已经编码过的视频禁止二次编码!!!
编码:编码是指对于高质量来源进行压缩编码,进一步节约体积。编码过程种主要进行片源处理,修复源较为明显常见问题,通常包括脏边、色带、碎块、颜色偏差、伽马矫正等;切除黑边,去除源中16:9比例下的黑色边框;压制空间,主要将源采用更高的压缩方式进行重新编码,通常为有损方式。
透明度对比:透明度是评价源于编码之间的相似程度的指标。良好的透明度是指在有经验的编码人员下都不能较为明显区分压制作品与源之间的差距。
根据I、P、B帧的功能,在编码过程中,编码器一般会尊重I帧内容,哪怕再劣质的压制,都不会对其进行明显的转换;而针对p帧,编码器可以转化为B帧进行编码节约空间,对于B帧进行重新编码。因此透明度应该从源与压制中P->B以及B->B的转换质量对比评判的压制质量。
Bloating:称为臃肿,是指实现在相同透明度情况下,码率较高。根据压制较为广泛接受的规则,当压制作品太过接近源的码率也被认为Bloating,数值如下表:
1080p | 720p | 576p | 480p | |
---|---|---|---|---|
原盘码率比例 | 75% | 50% |
--crf * --preset placebo --profile high --threads auto --deblock -3,-3 --me umh --merange 32 --rc-lookahead 60 --aq-mode 2 --no-mbtree --aq-strength 1.0 --qcomp 0.60 --psy-rd 1.0:0.00 --bframes 16 --ref *
ref计算方法:
-D 10 --preset veryslower --high-tier --ctu 32 --rd 4 --subme 7 --ref 6 --pmode --no-rect --no-amp --rskip 0 --tu-intra-depth 4 --tu-inter-depth 4 --range limited --no-open-gop --no-sao --rc-lookahead 100 --no-cutree --bframes 8 --vbv-bufsize 160000 --vbv-maxrate 160000 --colorprim bt709 --transfer bt709 --colormatrix bt709 --deblock -3:-3 --ipratio 1.3 --pbratio 1.2 --qcomp 0.6 --aq-mode 1 --aq-strength 1.0 --psy-rd 1.00 --psy-rdoq 1.00
-D 10 --crf * --preset slower --level-idc 5.1 --high-tier --ref 6 --bframes 8 --rd 4 --me star --subme 5 --merange 57 --ipratio 1.3 --pbratio 1.2 --aq-mode 4 --aq-strength 1.00 --qcomp 0.60 --psy-rd 1.25 --psy-rdoq 1.00 --ctu 32 --rc-lookahead 60 --deblock -3:-3 --cbqpoffs 0 --crqpoffs 0 --qg-size 8 --range limited --no-frame-dup --selective-sao 0 --no-cutree --tu-intra-depth 4 --tu-inter-depth 4 --rskip 0 --no-tskip --no-early-skip --no-rect --no-amp --no-sao --aud --repeat-headers --hrd --hdr-opt --colorprim bt2020 --colormatrix bt2020nc --transfer smpte2084 --master-display "G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(40000000,50)" --max-cll=577,512 --chromaloc 2 --pmode
其中的HDR参数应根据源进行计算设置
全套软件打包(请联系FRDS相关人员获取)
- Mediainfo:媒体信息检查软件,查看片源以及压制信息使用。
- MKVToolNix:mkv混流软件,也能实现以下基本的视频分割。
- SubtitleEdit:字幕编辑软,可以实现ORC等功能。
- eac3to :音轨转码编辑软件,也可实现Demux等功能。推荐使用eac3to with UsEac3to版本,并应包含一些对应的其他转换格式插件。
- BDinfo:蓝光原盘信息检测分析软件。
基础部分软件直接使用或者安装即可。 AVS和VS为两种方向,推荐选VS
AviSynth+:AVS最新版地址,请下载最新的非beta版本。
安装过程请选择x64,不要选择x86。其他非必须部分,根据需求进行安装。
AvsPmod:AVP是AVS的编辑器,具有实时预览、代码纠错复杂等功能。原本项目停止更新只有32位版本,新版被他人继续开发推出了64版本,下载选择64位版本,软件解压即可使用。
plugins64:plugins是AVS的各类插件和路径,需要手动安装。这里使用sc@PTP在论坛里提供的打包文件,直接解压到AVS对应目录里即可,目录默认位置为安装位置内,64位为plugins64+,提取压缩版对应plugins64+替换即可。链接: https://pan.baidu.com/s/1xaWRJuFm9qFSqcIOt4qtHQ 提取码: 684a
AviSynth、AvsPmod、plugins的位数必须相同,使用32位请所有版本都是32位
VapourSynth是基于python编写新一代的视频处理工具,解决了许多AVS遗留的问题,显著提高了运行速度,但是vs的学习难度较高,入门较为困难,教程较少。整体使用上vs比avs提高了很多,推荐有python基础的人直接入门学习。
Python:安装VS之前必须装好Python环境,不同VS版本要求的Python版本不同,下载安装前请先看好所需要的Python版本。安装时候必须选择 Add Python to PATH !!
VapourSynth:VapourSynth的主体安装程序,安装过程推荐安装所有推荐内容。除了安装位置外推荐使用默认设置。安装完后只包括主程序,以及官方的自带的插件,VS使用过程需要大量的插件:主要分为Script脚本和Plugins插件两个部分。安装插件脚本,需要将对应文件放入对应目录,目录在官方文档内有详细介绍。在Windows下官方提供了方便的下载管理插件。下文对于使用到部分将会介绍,但是其他内容请参阅官方文档。
VSRepoGUI:官方提供了方便的下载管理插件的GUI界面,下载解压后点开后即可使用,推荐放在VS的安装目录内。
通过软件可以查看对应的VS安装信息和脚本插件的所在位置,同时可以实现对插件的脚本安装、更新和卸载,软件插件安装位置,再右上角可以快速点开。在Windows下推荐本软件进行维护插件和脚本。
VapourSynth Editor:VS Editor是目前较为广泛使用的VS编辑器。下载后,直接解压即可使用。第一次使用时候,需要配置VapourSynth文件的位置。VS plugins paths 可以是用VSRepoGUI中的路径进行查看。
独立版本
使用压制工具大部分核心都是x264和x265(x265如无必要不在重复)。本人推荐压制软件功能越为简单越好,推荐2个使用,适合新手的**Simple x264/x265 Launcher以及适合有经验的纯命令行(CLI)的x264.exe和x265.exe**。Simple下载安装即可使用,本教程将以此为基础进行讲解。工具需要简单的设置,推荐log文件保存等设置,根据个人习惯修改。
大部分压制组要求,压制工具要求及时更新,使用最新版的压制工具。
要想做一个较为高质量作品,应采用最好的来源进行压制。HDR电影来源较为单一,4k的原盘和Remux资源为主,版本较少能选择不多。SDR目前可用压制版本较多,各个发行商的在不同时期也发行过不同蓝光版本,随着web的兴起,AZ和NF也都发布了较高码率的4k的sdr版本,所以在SDR压制时,需要对于来源进行对比,选取最为高质量的来源进行压制。对于蓝光原盘与remux两者相同时候,推荐使用Remux的更为方便。
对于原盘使用BDInfo检查原盘信息,查看原盘主要视频对应播放列表。对于复杂原盘,可能出现多版本混合的情况,需要确定所需要版本对应的MPLS,并确定原盘的主要码率 。在压制前推荐进行分离提取(Demux)后再进行压制。
原盘的分离提取可以与音频格式转换一起通过eac3to进行,但eac3to软件对于SUP字幕分离时候出现问题,所以要对sup字幕正确性检查。
将对应的MPLS的文件拖入,在1选择想要转换的内容和要转换的格式添加,需要对应附加参数的在第二部分添加,并指定好文件输出位置后运行代代码,注意输出文件名不要重复。下面提供一些一下常用格式以及对应参数表。eac3to的cli命令行使用方法网络有很多教程,这里不在详细赘述。
参数格式 | 需要添加参数 | 实例 |
---|---|---|
AC3-640 | 无 | |
AC3-448 | -448 | |
压制前一般需要对片源就行处理,一般包括去除黑边、修复脏边脏线、去除片源的一些问题等,并且在压制时一般需要进行部分压制测试,也需使用脚本进行实现。本节将对介绍压制中的最基本脚本的编写,分为VS和AVS两个部分。编写脚本使用对应的编辑器较为方便。以及基础例子如下
FFVideoSource("J:\BluryBD\After.the.Storm.2016.BluRay.Remux.1080p.AVC.TrueHD.5.1-HiFi.mkv")
Crop(0, 20, -0, -22)
FillBorder(0,1,0,0)
bbmod(2,0,0,0,128,21)
Z_Spline36Resize(1280, 692,dither="error_diffusion")
import vapoursynth as vs
import kagefunc as kgf
import fvsfunc as fvf
import havsfunc as haf
import vsTAAmbk as taa
import mvsfunc as mvf
import muvsfunc as muf
import nnedi3_resample as nnrs
import nnedi3_rpow2 as nnrp
#导入相关函数(上面导入的很多范例脚本中没有使用,不过去交错那用到了haf)
core = vs.get_core()
#请依据自己内存调整(单位MB)
core.max_cache_size = 27384
#加载片源输入即为16bit色深
src = core.lsmas.LWLibavSource(source=r"J:\BluryBD\After.the.Storm.2016.BluRay.Remux.1080p.AVC.TrueHD.5.1-HiFi.mkv",format="yuv420p16")
#另一种加载片源
#src = core.ffms2.Source(source=r'J:\BluryBD\After.the.Storm.2016.BluRay.Remux.1080p.AVC.TrueHD.5.1-HiFi.mkv')
#通常来说,有些比较特殊的片源可能在ffms2或lsmas下会有不正常的表现或者报错,故有时候需要更换使用
#处理前调整为16bit色深,可以降低运算带来的损失,lsmas不需要这个步骤
#src = fvf.Depth(src, 16)
#切边
src=core.std.Crop(src, left=0, right=0, top=20, bottom=20)
#脏边处理相关
#src = core.fb.FillBorders(src, 0, 1, 0, 0, mode="fillmargins")
#src = core.edgefixer.Continuity(src,left=4, right=4, top=0, bottom=0)
#将分辨率(压制为720p)
#src=core.resize.Spline36(src, 1280, 692)
#转为10bit再输出,x265一般压制为10bit,x264为8bit
src = fvf.Depth(src, 10)
#去交错(正常不需要使用)
#src = haf.QTGMC(src, Preset="slow", TFF=True)
#去锯齿
#src = taa.TAAmbk(src, aatype=-3, preaa=-1, strength=0, mtype=2, opencl=True)
src.set_output()
Tips:
1.修复脏边脏线以及去色带等属于进阶部分,将单独介绍
载入片源需要使用对应的解码器,ffm2(ffmpeg)是目前脚本广泛使用的解码器,支持格式较为广发,其第一次载入时需要进行全片的检索。
FFVideoSource(str filePath) #指定文件的路径
src = core.ffms2.Source(str source) #指定文件的路径
Tips:
1.右键可以直接选择插入文件完整路径。
2.首次执行载入预览会卡死,需要等待一定时间。
Crop(clip, int left=0,int top=0,int -right=0,int -bottom=0) #切割必须为偶数,right与bottom为负数
clip=core.std.Crop(clip, int left=0, int right=0, int top=0, int bottom=0) #切割必须为偶数
Tips:
1.Crop切割方式只能以偶数方式切割,奇数切割属于进阶内容
2.切割奇数边需要使用下节介绍的resize方法
z_Spline36Resize(int Width, int height, int src_left=?, int src_top, int src_width, int src_height, str dither) #
clip = core.resize.Spline36(clip clip, int Width, int height) #
压制前使用脚本一般间断抽取共约5k~10K帧进行参数测试,需要在脚本进行抽取。
SelectRangeEvery(int every, int length, int offset) #every为间隔,length为长度,offset为启示帧数
select=core.std.SelectEvery(clip[8000:-8000],cycle=4000, offsets=range(10))
clip= core.std.AssumeFPS(select, fpsnum=clip.fps.numerator, fpsden=clip.fps.denominator)
在压制前应该进行参数测试,以便获取较高的压制质量,一般需要确定合理码率大小(crf)以及对于码率分配参数(ap-mode、ap-s、qcomp)以及psy等重要参数进行测试。使用抽取测试代码,大约抽取6k帧进行参数测试,送入Simple-x264进行测试。
使用Simple进行压制,其设置如下所示。在设置界面记得开始log自动保存!!!
--level 4.1 --threads auto --vbv-bufsize 78125 --vbv-maxrate 62500 --colormatrix bt709 --colorprim bt709 --no-mbtree --no-dct-decimate --min-keyint 24 --me umh --merange 48 --deblock=-3,-3 --ipratio 1.3 --pbratio 1.2 --qcomp 0.6 --aq-mode 1 --aq-strength 0.8 --psy-rd 1.00:0.00
CRF测试主要确定合适码率,根据压制目标,确定合理的码率。推荐测试起始CRF为17,根据范围码率以0.5步进进行CRF测试。
压制效果受码率影响很大,在追求体积时,很容易造成欠码的问题。所以要设置合理的码率范围,防止出现因为码率不足导致的质量问题。需要主要检查需要码率较高的场景,例如,复杂的场景和暗的场景。
主要辨别问题有:
- 是否新产生了新的block
- 复杂的场景的细节是否丢失
- 是否压出明显的色带
前景无损失,背景没有明显损失
本部分十分建议进行,但是对于一些压制组不是强制要求。可以编写脚本进行批量测试
确定合理的码率后,切换2-pass方式使用预计码率,采用单一变量方式进行参数测试,每次测试只改变一个参数,每个参数推荐测试范围如下:
参数 | 真人类型 | 步进 |
---|---|---|
qcomp | ||
在新参数下,进行最终使用的crf测试。
# 导入压制使用的脚本文件,并添加帧信息与名字
a=import("C:\Path\To\source.avs").subtitle("Source", align=9).ffinfo(framenum=true,frametype=true,cfrtime=false,vfrtime=false,version=false,cropping=false,colorrange=false,colorspace=false,sar=false)
# 导入压制后的对比的视频文件
b=ffvideosource("C:\Path\To\b.mkv").subtitle("b", align=9).ffinfo(framenum=true,frametype=true,cfrtime=false,vfrtime=false,version=false,cropping=false,colorrange=false,colorspace=false,sar=false)
# 其他的压制文件
c=ffvideosource("C:\Path\To\c.mkv").subtitle("c", align=9).ffinfo(framenum=true,frametype=true,cfrtime=false,vfrtime=false,version=false,cropping=false,colorrange=false,colorspace=false,sar=false)
# 交错视频文件
interleave(a,b)
import vapoursynth as vs
core = vs.get_core()
# 生成帧信息,并打入标签
def FrameInfo(clip, title,
style="sans-serif,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,0,7,10,10,10,1"):
import functools
def FrameProps(n, clip):
clip = core.sub.Subtitle(clip, "Frame " + str(n) + " of " + str(
clip.num_frames) + "\nPicture type: " + clip.get_frame(n).props._PictType.decode(), style=style)
return clip
clip = core.std.FrameEval(clip, functools.partial(FrameProps, clip=clip))
clip = core.sub.Subtitle(clip, ['\n \n \n' + title], style=style)
return clip
# VS editor输出显示bug,对于压制后的文件需要进行,进行处理。
def outfix(clip):
encode = core.std.SetFrameProp(clip,prop="_Matrix",delete=True)
encode = core.std.SetFrameProp(encode,prop="_Transfer",delete=True)
encode = core.std.SetFrameProp(encode,prop="_Primaries",delete=True)
return encode
#-------------用于压制脚本的滤镜部分(例子)----------------#
#复制自己脚本出了导入,和输出部分内容
video = core.ffms2.Source(source=r'/Users/hujingyu/Encode/Paris.Texas.1984.1080p.BluRay.Remux.AVC.DTS-HD.MA.5.1-PmP.mkv')
video=core.std.Crop(video,64,64, 0, 0)
select=core.std.SelectEvery(video[8000:-8000],cycle=4000, offsets=range(80))
video= core.std.AssumeFPS(select, fpsnum=video.fps.numerator, fpsden=video.fps.denominator)
#-------------用于压制脚本的滤镜部分----------------#
video=FrameInfo(video,"source")# 标记信息
#-------------encode文件-------------------------#
encode=core.ffms2.Source(source=r"/whalehu/Encode/encode.mkv") # 载入视频
encode=FrameInfo(encode,"encode") # 标记信息
encode=outfix(encode)# 输入修复
out = core.std.Interleave([video,encode]) # 交叉帧
out.set_output()
将压制脚本中的测试抽帧代码注释掉,进行正式压制。
清晰度越高需要的时间越长,推荐使用较低的分辨率入门
封装是将所有素材合成一个mkv的视频文件,封装是一个很简单的工作,没有技术难点,但是封装的好坏会对压制作品评价很为重要,封装主要是认真。这里主要介绍被广泛接受的封装细节,不同压制组对这个有具体的细节要求。
一般封装主要注意以及下内容:
-
视频、音轨和字幕是否匹配
-
音轨和字幕是否设置了正确的语言标签
-
需要标准命名的音轨是否正确
-
章节信息和标题是否添加并正确命名
-
正确命名文件标题
文件标题并不是文件名!!!一般主要为IMDB的英文标题并可以添加小组信息
原盘若没有章节信息,推荐5-10min间隔生成章节点