Little H title

this is subtitle


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 公益404

highlight.js高亮你的代码

发表于 2018-03-06 | 分类于 newbie项目

highlight代码高亮的使用

各种highlight风格demo预览

官网usage教程

Getting Started

当然可以下载,然后引入,再初始化
一共3句话

1
2
3
4
5
6
<!-- 这个是风格显示选择 -->
<link rel="stylesheet" href="/path/to/styles/default.css">
<!-- 这个是highlight本体 -->
<script src="/path/to/highlight.pack.js"></script>
<!-- Attaches highlighting to the page load event 不就是onload的时候执行渲染么,也就是说,在此之后改变document都不会在执行了-->
<script>hljs.initHighlightingOnLoad();</script>

不过当然推荐的是用CDN了,还是去bootCND上找了

在使用时,一定要将你要展示的代码包在<pre><code></code></pre>标签里!!! 它会自动匹配语言进行高亮,如果没有高亮,可以进行手动匹配,加上class

1
<pre><code class="html">...</code></pre>

支持的语言列表

如果不想要高亮了,class选nohighlight

1
<pre><code class="nohighlight">...</code></pre>

highlight API文档

一些问题注意

  1. 如果你的代码里包含标签,记得将标签的”<”换成”&lt”,把”>”换成”&gt”

  2. 从接口中取出来的代码是不会在高亮的,这个问题不就是onload的时候执行渲染么,也就是说,在此之后改变document都不会在执行了。所以很显然这样并不能高亮从接口取会来的文档的代码。

最终解决问题的方法是接口返回使用highlight.js编译好的html,因为后端使用的是node,用marked就解决了这个问题。只需要在marked的配置中添加highlight项即可(要先npm install highlight.js):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//这里参数看不明白就看marked那篇
var marked = require('marked');
var highlight = require('highlight.js');
marked.setOptions({
renderer: new marked.Renderer(),
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false,
highlight: function (code) {
return highlight.highlightAuto(code).value;
}
});

然后返回的文档已经添加了对应的class。

当然highlight: function(code, lang, callback)有三个参数可以展开介绍

Font Awesome一套绝佳的图标字体库和CSS框架

发表于 2018-03-06 | 分类于 newbie项目

Font Awesome一套绝佳的图标字体库和CSS框架

Font Awesome为您提供可缩放的矢量图标,您可以使用CSS所提供的所有特性对它们进行更改,包括:大小、颜色、阴影或者其它任何支持的效果。

  • 一个字库,675个图标
    仅一个Font Awesome字库,就包含了与网页相关的所有形象图标。
  • 无需依赖JavaScript
    Font Awesome完全不依赖JavaScript,因此无需担心兼容性。
  • 无限缩放
    无论在任何尺寸下,可缩放的矢量图形都会为您呈现出完美的图标。
  • 如言语一般自由
    Font Awesome完全免费,哪怕是商业用途。请查看许可。
  • CSS控制
    只要CSS支持,无论颜色、大小、阴影或者其它任何效果,都可以轻易展现。
  • 高分屏完美呈现
    Font Awesome的矢量图标,将使您的网站在视网膜级的高分屏上大放异彩。
  • 完美兼容其它框架
    尽管是为Bootstrap设计,但Font Awesome同样能与其它框架完美协同运作。
  • 可用于桌面系统
    用于桌面系统,或需要一套完整的矢量图,请查看备忘。
  • 可适配于屏幕阅读器
    与其它字体不同,Font Awesome不会影响屏幕阅读器正常工作。

使用

最简单的方式:BootstrapCDN (由MaxCDN提供)

一句话将Font Awesome加入您的网页中。您完全不用下载或者安装任何东西!

  1. 将以下代码粘贴到网页HTML代码的 <head> 部分.
1
<link href="//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">

当新版本发布时,BootstrapCDN需要一点时间来同步到最新版本。稍安勿躁 :)

  1. 参考示例,然后开始使用Font Awesome吧!

简单方式之一:使用默认CSS

如果您使用了默认的Bootstrap CSS样式,那么你可以使用这种方式来引入默认的Font Awesome CSS样式。

  1. 复制整个 font-awesome 文件夹到您的项目中。
  2. 在HTML的 <head> 中引用font-awesome.min.css。
1
2
3
4
<link rel="stylesheet" href="path/to/font-awesome/css/font-awesome.min.css">

<!-- 当然也用CND了 -->
<link href="http://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">

简单方式之二:LESS Ruby Gem

简单方式之三:SASS Ruby Gem

使用实例

基本图标

您可以将Font Awesome图标使用在几乎任何地方,只需要使用CSS前缀 fa ,再加上图标名称。 Font Awesome是为使用内联元素而设计的。我们通常更喜欢使用 ,因为它更简洁。 但实际上使用 <span> 才能更加语义化(span在嵌套组合时可以用)。

1
<i class="fa fa-camera-retro"></i> 这是一个fa-camera-retro图标

如果您修改了图标容器的字体大小,图标大小会随之改变。同样的变化也会发生在颜色、阴影等其它任何CSS支持的效果上。

大图标

使用 fa-lg (33%递增)、fa-2x、 fa-3x、fa-4x,或者 fa-5x 类 来放大图标。

1
2
3
4
5
<i class="fa fa-camera-retro fa-lg"></i> fa-lg
<i class="fa fa-camera-retro fa-2x"></i> fa-2x
<i class="fa fa-camera-retro fa-3x"></i> fa-3x
<i class="fa fa-camera-retro fa-4x"></i> fa-4x
<i class="fa fa-camera-retro fa-5x"></i> fa-5x

如果图标的底部和顶部被截断了,您需要增加行高来解决此问题。

固定宽度

使用 fa-fw 可以将图标设置为一个固定宽度。主要用于不同宽度图标无法对齐的情况。 尤其在列表或导航时起到重要作用。

1
2
3
4
5
6
<div class="list-group">
<a class="list-group-item" href="#"><i class="fa fa-home fa-fw"></i>&nbsp; Home</a>
<a class="list-group-item" href="#"><i class="fa fa-book fa-fw"></i>&nbsp; Library</a>
<a class="list-group-item" href="#"><i class="fa fa-pencil fa-fw"></i>&nbsp; Applications</a>
<a class="list-group-item" href="#"><i class="fa fa-cog fa-fw"></i>&nbsp; Settings</a>
</div>

用于列表

使用 fa-ul 和 fa-li 便可以简单的将无序列表的默认符号替换掉。

1
2
3
4
5
6
<ul class="fa-ul">
<li><i class="fa-li fa fa-check-square"></i>List icons</li>
<li><i class="fa-li fa fa-check-square"></i>can be used</li>
<li><i class="fa-li fa fa-spinner fa-spin"></i>as bullets</li>
<li><i class="fa-li fa fa-square"></i>in lists</li>
</ul>

边框与对齐

使用 fa-border 以及 pull-right 或 pull-left 可以轻易构造出引用的特殊效果。

1
2
3
4
<i class="fa fa-quote-left fa-3x pull-left fa-border"></i>
...tomorrow we will run faster, stretch out our arms farther...
And then one fine morning— So we beat on, boats against the
current, borne back ceaselessly into the past.

动画

使用 fa-spin 类来使任意图标旋转,现在您还可以使用 fa-pulse 来使其进行8方位旋转。尤其适合 fa-spinner、fa-refresh 和 fa-cog 。

1
2
3
4
5
<i class="fa fa-spinner fa-spin"></i>
<i class="fa fa-spinner fa-pulse"></i>
<i class="fa fa-refresh fa-spin"></i>
<i class="fa fa-cog fa-spin"></i>
<i class="fa fa-circle-o-notch fa-spin"></i>

CSS3动画不支持IE8-IE9。

旋转与翻转

使用 fa-rotate-* 和 fa-flip-* 类可以对图标进行任意旋转和翻转。

1
2
3
4
5
6
<i class="fa fa-shield"></i> normal<br>
<i class="fa fa-shield fa-rotate-90"></i> fa-rotate-90<br>
<i class="fa fa-shield fa-rotate-180"></i> fa-rotate-180<br>
<i class="fa fa-shield fa-rotate-270"></i> fa-rotate-270<br>
<i class="fa fa-shield fa-flip-horizontal"></i> fa-flip-horizontal<br>
<i class="fa fa-shield fa-flip-vertical"></i> icon-flip-vertical

组合使用

如果想要将多个图标组合起来,使用 fa-stack 类作为父容器, fa-stack-1x 作为正常比例的图标, fa-stack-2x 作为大一些的图标。还可以使用 fa-inverse 类来切换图标颜色。您可以在父容器中 通过添加 大图标 fa-lg 类来控制整体大小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<span class="fa-stack fa-lg">
<i class="fa fa-square-o fa-stack-2x"></i>
<i class="fa fa-twitter fa-stack-1x"></i>
</span>
fa-twitter on fa-square-o<br>
<span class="fa-stack fa-lg">
<i class="fa fa-circle fa-stack-2x"></i>
<i class="fa fa-flag fa-stack-1x fa-inverse"></i>
</span>
fa-flag on fa-circle<br>
<span class="fa-stack fa-lg">
<i class="fa fa-square fa-stack-2x"></i>
<i class="fa fa-terminal fa-stack-1x fa-inverse"></i>
</span>
fa-terminal on fa-square<br>
<span class="fa-stack fa-lg">
<i class="fa fa-camera fa-stack-1x"></i>
<i class="fa fa-ban fa-stack-2x text-danger"></i>
</span>
fa-ban on fa-camera

Bootstrap 3 示例

Font Awesome 完全兼容 Bootstrap 的所有组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<a class="btn btn-danger" href="#">
<i class="fa fa-trash-o fa-lg"></i> Delete</a>
<a class="btn btn-default btn-sm" href="#">
<i class="fa fa-cog"></i> Settings</a>

<a class="btn btn-lg btn-success" href="#">
<i class="fa fa-flag fa-2x pull-left"></i> Font Awesome<br>Version 4.7.0</a>

<div class="btn-group">
<a class="btn btn-default" href="#"><i class="fa fa-align-left"></i></a>
<a class="btn btn-default" href="#"><i class="fa fa-align-center"></i></a>
<a class="btn btn-default" href="#"><i class="fa fa-align-right"></i></a>
<a class="btn btn-default" href="#"><i class="fa fa-align-justify"></i></a>
</div>

<div class="input-group margin-bottom-sm">
<span class="input-group-addon"><i class="fa fa-envelope-o fa-fw"></i></span>
<input class="form-control" type="text" placeholder="Email address">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-key fa-fw"></i></span>
<input class="form-control" type="password" placeholder="Password">
</div>

<div class="btn-group open">
<a class="btn btn-primary" href="#"><i class="fa fa-user fa-fw"></i> User</a>
<a class="btn btn-primary dropdown-toggle" data-toggle="dropdown" href="#">
<span class="fa fa-caret-down"></span></a>
<ul class="dropdown-menu">
<li><a href="#"><i class="fa fa-pencil fa-fw"></i> Edit</a></li>
<li><a href="#"><i class="fa fa-trash-o fa-fw"></i> Delete</a></li>
<li><a href="#"><i class="fa fa-ban fa-fw"></i> Ban</a></li>
<li class="divider"></li>
<li><a href="#"><i class="i"></i> Make admin</a></li>
</ul>
</div>

补充

1
<i class="fa fa-pencil-square" aria-hidden="true"></i>

Accessible Rich Internet Applications
图标的可访问性

现代的辅助技术能够识别并朗读由 CSS 生成的内容和特定的 Unicode 字符。为了避免 屏幕识读设备抓取非故意的和可能产生混淆的输出内容(尤其是当图标纯粹作为装饰用途时),我们为这些图标设置了 aria-hidden="true" 属性。

如果你使用图标是为了表达某些含义(不仅仅是为了装饰用),请确保你所要表达的意思能够通过被辅助设备识别,例如,包含额外的内容并通过 .sr-only 类让其在视觉上表现出隐藏的效果。

如果你所创建的组件不包含任何文本内容(例如, <button> 内只包含了一个图标),你应当提供其他的内容来表示这个控件的意图,这样就能让使用辅助设备的用户知道其作用了。这种情况下,你可以为控件添加 aria-label 属相。

fastclick 解决移动端click事件300ms延迟

发表于 2018-03-06

fastclick 解决移动端click事件300ms延迟

移动端click 事件延迟300ms

一般情况下,如果没有经过特殊处理,移动端浏览器在派发点击事件的时候,通常会出现300ms左右的延迟。也就是说,当我们点击页面的时候移动端浏览器并不是立即作出反应,而是会等上一小会儿才会出现点击的效果。在移动WEB兴起的初期,用户对300ms的延迟感觉不明显。但是,随着用户对交互体验的要求越来越高,现今,移动端300ms的点击延迟逐渐变得明显而无法忍受。

那么,移动端300ms的点击延迟是怎么来的呢?

产生原因

移动浏览器上支持的双击缩放操作,以及IOS Safari 上的双击滚动操作,是导致300ms的点击延迟主要原因。

预备知识:移动端点击一个元素触发事件的顺序

以下是四种touch和click事件
touchstart: //手指放到屏幕上时触发
touchmove: //手指在屏幕上滑动式触发
touchend: //手指离开屏幕时触发
touchcancel: //系统取消touch事件的时候触发,这个好像比较少用
click://在这个dom(或冒泡到这个dom)上手指触摸开始,且手指未曾在屏幕上移动(某些浏览器允许移动一个非常小的位移值),且在这个在这个dom上手指离开屏幕,且触摸和离开屏幕之间的间隔时间较短(某些浏览器不检测间隔时间,也会触发click)才能触发
上述事件发生顺序:在移动端,手指点击一个元素,会经过:touchstart —> touchmove -> touchend —>click。

双击缩放:顾名思义,即用手指在屏幕上快速点击两次,移动端浏览器会将网页缩放至原始比例。 那么这和 300 毫秒延迟有什么联系呢?
假定这么一个场景。用户在浏览器里边点击了一个链接。由于用户可以进行双击缩放或者双击滚动的操作,当用户一次点击屏幕之后,浏览器并不能立刻判断用户是确实要打开这个链接,还是想要进行双击操作。因此,浏览器就等待 300 毫秒,以判断用户是否再次点击了屏幕。
也就是说,移动端浏览器会有一些默认的行为,比如双击缩放、双击滚动。这些行为,尤其是双击缩放,主要是为桌面网站在移动端的浏览体验设计的。而在用户对页面进行操作的时候,移动端浏览器会优先判断用户是否要触发默认的行为。

解决方案

禁用缩放(全部缩放)

对于不需要缩放的页面,通过设置meta标签禁用缩放,表明这个页面是不需要缩放的,双击缩放就没有意义了。此时浏览器可以禁用默认的双击缩放行为并且去掉300ms的点击延迟。
该方法缺点在于必须通过完全禁用缩放来达到去掉点击延迟的目的,但我们初衷是想禁止默认双击缩放行为,这样就不用等待300ms来判断当前操作是否是双击。但是通常情况下我们还是希望能通过双指缩放来进行缩放操作,比如放大图片,很小的一段文字。

1
2
<meta name="viewport" content="user-scalable=no">
<meta name="viewport" content="initial-scale=1,maximum-scale=1">

更改默认视口宽度

移动端浏览器默认视口宽度一般比设备浏览器视窗宽度大,通常是980px,我们可以通过如下标签设置视口宽度为设备宽度。

1
<meta name="viewport" content="width=device-width">

因为双击缩放主要是用来改善桌面站点在移动端浏览体验的,而随着响应式设计的普及,很多站点都已经对移动端做过适配和优化了,这个时候就不需要双击缩放了,如果能够识别出一个网站是响应式的网站,那么移动端浏览器就可以自动禁掉默认的双击缩放行为并且去掉300ms的点击延迟。chrome 32+中,如果设置了上述meta标签,那浏览器就可以认为该网站已经对移动端做过了适配和优化,就无需双击缩放操作了。
这个方案相比方案一的好处在于,它没有完全禁用缩放,而只是禁用了浏览器默认的双击缩放行为,但用户仍然可以通过双指缩放操作来缩放页面。不足在于其他浏览器的支持有限。

css touch-action

指针事件(Point Event)最初由微软提出,现已进入 W3C 规范的候选推荐标准阶段 (Candidate Recommendation)。指针事件是一个新的 web 事件系列,相应的规范旨在使用一个单独的事件模型,对所有输入类型,包括鼠标 (mouse)、触摸 (touch)、触控 (stylus) 等,进行统一的处理。
例如,你可以只去监听一个元素的 pointerdown事件,无需分别监听其 touchstart和mousedown事件。其中有一个和点击延迟直接相关的实现 —— 一个名为 touch-action的新 CSS 属性。根据规范,touch-action
属性决定 “是否触摸操作会触发用户代理的默认行为。这包括但不限于双指缩放等行为”。
从实际应用的角度来看,touch-action决定了用户在点击了目标元素之后,是否能够进行双指缩放或者双击缩放。因此,这也相当完美地解决了 300 毫秒点击延迟的问题。touch-action的默为 auto,将其置为 none 即可移除目标元素的 300 毫秒延迟。
目前而言,Internet Explorer 实现了指针事件,同时,现在已经有一些指针事件的 polyfills 可以在项目中使用了

指针事件的 polyfill

指针事件的 polyfill 比较多,以下列出比较流行的几个。

  • Google 的 Polymer
  • 微软的 HandJS
  • @Rich-Harris 的 Points

为避免 300 毫秒点击延迟,我们主要关心这些 polyfill 是如何在非 IE 浏览器中模拟 CSS touch-action属性的,这其实是一个不小的挑战。由于浏览器会忽略不被支持的 CSS 属性,唯一能够检测开发者是否声明了 touch-action: none的方法是使用 JavaScript 去请求并解析所有的样式表。HandJS 也正是这么做的,但不管是从性能上来看还是其他一些复杂的方面,这都会遇到问题。
Polymer 则是通过判断标签上的 touch-action属性 (attribute),而非 CSS 代码。
这对于我们开发者来说意味着什么?如果你比较感兴趣,想深入指针事件,那上述 polyfill 就非常适合应用到手头的项目中。然而,你若只想寻求一个解决 300 毫秒点击延迟的方法,上述方案可能就有点过了,因为它们要么是资源密集型的方案,要么是touch-action属性的非标准化模拟。所以,接下去我们要来看一些专门针对 300 毫秒延迟而生的解决方案

zepto等库的 tap事件

zepto 的touch模块中自定义了tap事件,用于代替click事件,表示一个轻击操作。touch模块实现tap的原理是绑定事件touchstart,touchmove和touchend到document上,然后通过计算touch事件触发的时间差,位置差来实现了自定义的tap,swipe等。
zepto自定义的tap操作虽然可以解决300ms点击延迟问题,但存在著名的“点透”问题。不知其最新版本有没有解决该问题。

fastclick 解决300ms延迟。

FastClick 是 FT Labs 专门为解决移动端浏览器 300 毫秒点击延迟问题所开发的一个轻量级的库。

  • 基本原理:FastClick的实现原理是在检测到touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件,并把浏览器在300ms之后真正的click事件阻止掉。
  • fastClick的核心代码
1
2
3
4
5
6
7
FastClick.prototype.onTouchEnd = function(event){ // 一些状态监测代码 
// 从这里开始,
if (!this.needsClick(targetElement)) { // 如果这不是一个需要使用原生click的元素,则屏蔽原生事件,避免触发两次click
event.preventDefault(); // 触发一次模拟的click
this.sendClick(targetElement, event);
}
}

这里可以看到,FastClick在touchEnd的时候,在符合条件的情况下,主动触发了click事件,这样避免了浏览器默认的300毫秒等待判断。为了防止原生的click被触发,这里还通过event.preventDefault()屏蔽了原生的click事件。

通过sendClick模拟click事件:

1
2
3
4
5
6
7
FastClick.prototype.sendClick = function(targetElement, event) { // 这里是一些状态检查逻辑
// 创建一个鼠标事件
clickEvent = document.createEvent('MouseEvents'); // 初始化鼠标事件为click事件
clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); // fastclick的内部变量,用来识别click事件是原生还是模拟
clickEvent.forwardedTouchEvent = true; // 在目标元素上触发该鼠标事件,
targetElement.dispatchEvent(clickEvent);
}

就目前而言,FastClick 非常实际地解决 300 毫秒点击延迟的问题。唯一的缺点可能也就是该脚本的文件尺寸 (尽管它只有 10kb)。

对比总结

禁用缩放:简单,但同时也使的网页无法缩放,不适用于未对移动端浏览做适配优化的网页。
更改默认视口宽度:简单,但需要浏览器支持。
指针事件和css touch-action:新属性,可能存在浏览器兼容问题,如仅为解决点击延迟问题儿引入一整套指针事件有点过了。
tap事件:能较好解决点击延迟,并且对其他移动端触摸事件也有较好支持,但存在点透问题,不知最新版是否解决。
fastclick:当前较好的专门解决点击延迟的库,脚本尺寸相对较大。

参考链接

使用fastclick

1
2
3
4
5
6
7
8
9
10
11
npm install fastclick -S

// 解决移动端300ms延迟问题
var attachFastClick = require('fastclick');
attachFastClick(document.body);

// 解决移动端300ms延迟问题
if (typeof window !== "undefined") {
const Fastclick = require('fastclick')
Fastclick.attach(document.body)
}

tmux简单使用

发表于 2018-02-25 | 分类于 linux

tmux简单使用

安装

ubuntu下

1
sudo apt-get install tmux

安装完后运行

基本概念

Tmux基于典型的c/s模型,主要分为会话、窗口和面板三个元素:

  • Session:输入tmux后就创建了一个会话,一个会话是一组窗体的集合。
  • Window:会话中一个当前活动的窗口。
  • Pane:一个窗口可以分成多个面板

tmuxbase

图中左下角的3显示为当前会话,随后1 vim,2 bash,3 ssh 分别是3个窗口,蓝色bash表示当前窗口.
图中用蓝色数字标记的1,2,3分别是bash窗口的三个面板(Pane)。你还可以在tmux配置文件中给状态栏添加时间、天气等信息。

操作(有个前缀)

Tmux的所有操作必须使用一个前缀进入命令模式,默认前缀为ctrl+b,很多人会改为ctrl+a,你可以修改tmux.conf配置文件来修改默认前缀:

1
2
3
4
#前缀设置为<Ctrl-a>
set -g prefix C-a
#解除<Ctrl-b>
ubind C-b

窗格操作(Pane)

  • % 向右平分出两个窗格
  • “ 向下平分出两个窗格
  • x 关闭当前窗格(当窗口中只剩一个pane时,就是关闭窗口)
  • q 显示所有窗格的序号,在序号出现期间按下对应的数字,即可跳转至对应的窗格
  • { 当前窗格前移(所有窗口大小不变,内容按从上往下,从左往右。往前走)
  • } 当前窗格后移
  • ; 选择上次使用的窗格,只能记住一次
  • o 选择下一个窗格,也可以使用上下左右方向键来选择(改成vim的 hjkl)
  • space 切换窗格布局,tmux 内置了五种窗格布局,也可以通过 ⌥1 至 ⌥5来切换
  • z(zoom) 最大化当前窗格,再次执行可恢复原来大小

窗口操作(window)

tmux 除了窗格以外,还有窗口(window) 的概念。依次使用以下快捷键来熟悉 tmux 的窗口操作:

  • c(create) 新建窗口,此时当前窗口会切换至新窗口,不影响原有窗口的状态
  • & 关闭当前窗口
  • p(previous) 切换至上一窗口
  • n(next) 切换至下一窗口
  • w(window) 窗口列表选择,注意 macOS 下使用 ⌃p 和 ⌃n 进行上下选择
  • l 在前后两个窗口间互相切换
  • 0 切换至 0 号窗口,使用其他数字 id 切换至对应窗口(0~9,在10往上就不行了)
  • . 修改当前窗口编号;相当于窗口重新排序(一个是编号,一个是名字1:~xioaming)
  • ,(搜狗) 重命名窗口,可以使用中文,重命名后能在 tmux 状态栏更快速的识别窗口 id
  • f(find) 根据窗口名搜索选择窗口,可模糊匹配
  • ctrl+方向 调整窗口大小(技巧:按住ctrl+k再按方向键)

会话操作(session)

如果运行了多次 tmux 命令则会开启多个 tmux 会话(session)。在 tmux 会话中,使用前缀快捷键 ⌃b 配合以下快捷键可操作会话:

  • s(session) 选择会话列表,就是开了几个tmux
  • d detach 当前会话,运行后将会退出 tmux 进程,返回至 shell 主进程(但会话列表仍在,就是退出与保存)
  • $ 重命名当前会话
  • : 进入命令行模式;此时可以输入支持的命令,例如kill-server可以关闭服务器
  • [ 进入复制模式;此时的操作与vi/emacs相同,按q/Esc退出([ space 鼠标 enter])
    1. 按前缀+[ 进入复制模式
    2. 按一下 space 开始复制,方向键选择复制区域
    3. 按 Enter 复制并退出copy-mode。
    4. 将光标移动到指定位置,按前缀+ ] 粘贴

在 shell 主进程下运行以下命令可以操作 tmux 会话:

1
2
3
4
5
6
7
8
tmux ls # 列出所有 tmux 会话
//新建与打开
tmux new -s foo # 新建名称为 foo 的会话
tmux a # 恢复至上一次的会话
tmux a -t foo # 恢复名称为 foo 的会话,会话默认名称为数字
//删除
tmux kill-session -t foo # 删除名称为 foo 的会话
tmux kill-server # 删除所有的会话

除以上提到的快捷键以外,tmux 还有许多其他的快捷键和命令,使用前缀快捷键 ctrl+b 加 ? 可以查看所有的快捷键列表,该列表视图为 tmux copy 模式,该模式下可使用以下快捷键(无需加 ⌃b 前缀):

  • ⌃s 向前搜索
  • q 退出 copy 模式
  • ⌃v 下一页 翻页也可用pageup pagedown
  • Meta v 上一页 (tmux 快捷键为 Emacs 风格,这里的 Meta 键可用 Esc 模拟)

常见配置与问题

1、鼠标滚屏

tmux 默认配置中最糟糕的体验就是滚屏查看和文本复制(大家可以先试试看)。你需要先使用 ⌃b [ 快捷键进入 copy 模式,然后使用翻页、字符定位来选择需要的字符,效率远没有鼠标选择来的快。

因此 tmux 提供了一些个性化配置项来优化这些配置,首先在 shell 中运行 touch ~/.tmux.conf 新建用户配置文件。在文件中增加以下内容:

1
2
3
4
5
6
7
8
9
10
11
# 开启鼠标模式
set -g mode-mouse on
​
# 允许鼠标选择窗格
set -g mouse-select-pane on
​
# 如果喜欢给窗口自定义命名,那么需要关闭窗口的自动命名
set-option -g allow-rename off
​
# 如果对 vim 比较熟悉,可以将 copy mode 的快捷键换成 vi 模式
set-window-option -g mode-keys vi

配置文件修改完成后,可以 tmux kill-server 重启所有 tmux 进程,或者在 tmux 会话中使用 ctrl+b : 进入控制台模式,输入 source-file ~/.tmux.conf 命令重新加载配置(ubuntu上没这命令)。

2、 pane切换

切换面板就和vim一样了,方向键太变扭了

1
2
3
4
5
# map Vi movement keys as pane movement keys
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

3、美化 tmux-powerline

就是我的效果达不到例子那样

https://github.com/erikw/tmux-powerline

ubuntu上优化

发表于 2018-02-14 | 分类于 linux

ubuntu16.04 上手要做的事

主要是

  1. 音频播放器
  2. 视屏播放器
  3. 编程IDE vsc
  4. 桌面美化

sudo apt-get update //获取最新系统安装的软件版本列表
sudo apt-get dist-upgrade //升级系统软件,不过这之前可以改个源,system setting,soteware中改aliyun或163的都可以
sudo apt-get autoremove //自动移除没有依赖的软件
sudo apt-get autoclean //删掉软件的升级的安装包

装个命令行vim 如果是物理机先搞显卡驱动

chmod 777 /etc/sudoers 默认是440,改完别退出sudo 然后编辑这个文件vim
不该也没事,这是改的没有密码的登录而已,然后再改回440

安装方式

详细情况见 ubuntu上安装软件方法

  1. sudo apt-get
  2. 如果是deb的可以使用
  3. .tar.gz的先tar -x

安装mac主题包

sudo apt-get install gnome-tweak-tool

自己百度ubuntu14.04 mac

mongodb使用

发表于 2018-02-09 | 分类于 前端

参考文档,菜鸟
mongoDB入门

mongodb使用

下载及安装

按window上的来,下载并安装好到默认路径,并配置好环境变量(这样才能在cmd命令行中打入mongo就能运行)
path

要用到的命令也就那几个
mongod 打开或创建数据库
mongo 连接数据库才能继续其他操作
mongoimport 导入数据库
mongo

创建数据库目录并在命令行下运行 MongoDB 服务器

MongoDB将数据目录存储在 db 目录下。但是这个数据目录不会主动创建,我们在安装完成后需要创建它
名字随便取,就建个db,注意不要放在C:\Program Files\MongoDB下

会提示Invalid command: FilesMongoDBdb
毕竟路径中有空格
换一个位置,换到C:\Users\db下也不行,说是只读 不允许
那就干脆放到D盘下

为了从命令提示符下运行 MongoDB 服务器,你必须从 MongoDB 目录的 bin 目录中执行 mongod.exe 文件。

1
2
//改到D:\db
mongod --dbpath D:\db

连接MongoDB(这个是在上面打开服务器的基础上)

我们可以在命令窗口中运行 mongo.exe 命令即可连接上 MongoDB,执行如下命令:

1
$ mongo

感觉这个用git bash来操作不好
因为看下图比较, 就是没有提示符了
showdbs1
showdbs2

配置 MongoDB 服务(跳过)

管理员模式打开命令行窗口

创建目录,执行下面的语句来创建数据库和日志文件的目录

1
2
mkdir c:\data\db
mkdir c:\data\log

主要一个log日志文件,db前面已将创建了

一些常用命令(连接Mongo后)

总结下前面的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
mongod:
mongod --dbpath <path>
mongo:
show dbs //查看所有数据库(空的数据库不显示,注意insert({}) 这个也是插入了东西,会显示的。和remove({})一样哦 )
db //db 命令查看当前数据库名,也表示当前数据库
show collections //查看当前库的所有集合
show users //查看当前库有哪些用户
show profile
show log

增 use <dbname> //使用或创建数据库
db //查看当前是哪个数据库 show dbs看不到,因为test中没有数据
删 db.dropDatabase() //删除当前数据库(要进到删除的数据库中么?先use到,在drop),默认为 test,你可以使用 db 命令查看当前数据库名。删除后db下还是在被删除掉的数据库中,不过show dbs已经看不到了,和use创建那会一样

改
查 db / show dbs



//collections都是BSON格式 当JSON好了 BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON。
增 db.collectionName.insert({"name":"pipi"}) //用json格式写入就好了,可以show dbs可以看到,当然可以定一个变量咯,然后插入。这个插入就只是插入,即使同名也插入,不会替换/合并等。都当做那条集合中的记录

删 db.collectionName.drop() //删了当前数据库所有集合中叫collectionName的一个集合

db.collection.remove( //这个是移除某个集合中的一条记录
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)

db.col.remove({}) //删除一个collection中所有记录,这不就是drop么?不对。drop后是在show collections中也看不到了
db.col.remove({'age': 1}) //删除所有age=1的
db.col.remove({'age': 1}, {justOne: true}) //删除所有age=1的中第一条匹配的
//remove drop dropDatabase

查 db.collectionName.find() //查找当前数据库中collectionName这个集合的所有记录
find({k: v}) //查一个对象,age=3的就是{k:v}还是个模糊查询
find({k: {$ne: v}}) //查一个对象,age!=3的就是{k:v}还是个模糊查询
find({k: v},{k: v}) //查多个对象,多个条件用逗号,AND隔开
find($or: [{k: v},{k: v}]) //这是OR,当然AND和OR也能一起用
//条件查询 > <
find({ k: {$gt: v} }) gte
find({ k: {$lt: v} }) lte
find({ k: {$gt: v, $lt: v}, k: {$gt: v, $lt: v} }) //合起来
find().limit(5) //查出来了结果过滤,取前5条
find().skip() //这是跳过几条
find().pretty() //格式更好点
排序 find().sort({k1: 1}, {k2, -1}) //按k1排序,k1相同就按k2, 1表正序,-1逆序

改 //使用 update() 和 save() 方法来更新集合中的文档. 一个是更新,个是替换
//update() 方法用于更新已存在的文档
//save() 方法通过传入的文档来替换已有文档

db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>, //默认查询第一条匹配的,true之后是所有的
writeConcern: <document>
}
)
//用到了$set: db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
//以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi 参数为 true。
//$ db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}},{multi:true})

db.collection.update({
{k, v},
{$set: {k, v2} 修改
}
})
db.collection.update({
{k, v},
{k1, v1, k2, v2} 替换
})

db.collection.save(
<document>,
{
writeConcern: <document>
}
)

mongoimport: 导入一个BSON
mongoimport --db test --collection user --drop --file D:\db\1.json

最后说下nodejs连接MongoDB

基于 PotPlayer 和 madVR 的播放器教程

发表于 2018-02-08 | 分类于 多媒体

原文链接,本blog只是做个非商业学习存档
[VCB-Studio 科普教程 2.5] 基于 PotPlayer 和 madVR 的播放器教程

[VCB-Studio 科普教程 2.5] 基于 PotPlayer 和 madVR 的播放器教程

Potplayer 是高清影视常用的播放器,界面简洁,功能齐全,比 MPC-HC 和 MPC-BE 更人性化;但其默认方案十分糟糕,预设过多错误,无法正确播放 10-bit 视频,一直饱受诟病。VCB-Stuido 以往发布的数篇高清教程大多偏重于 madVR,在 PotPlayer 的设置方面有些错漏。为了广大观众能正确、便捷地用 PotPlayer 享受高清影视,我们为大家带来一篇基于 PotPlayer 的高清影视全套 64-bit 工具链完整配置图文详解教程。

本教程花大力气调整 Potplayer ,很大程度上是为了纠正 Potplayer 错误的默认设置,让它能跟 MPC-HC 和 MPC-BE 站到同一起跑线上。如果 VCB-Studio 其他播放器教程中的 Potplayer 设置与本篇有冲突,以本篇教程为准。如果看不清图片,请在图片上右键点击-在新选项卡中打开,查看大图。先看完教程再跟着教程操作

工具安装篇

1、为了避免版本混乱导致的bug,本教程提供所全套 64-bit 工具:

PotPlayer(播放器),LAV Filters(分离/解码器),madVR(视频渲染器),xy-vsFilter(通用字幕插件),xy-SubFilter(madVR专用字幕插件)。下载链接:百度网盘 密码:fvq7

安装路径只允许纯英文,否则一些工具会无法使用,故建议单独建一个纯英文路径的文件夹 Tools,把这些以上提到的程序都放进去,方便更新与维护。

2、安装 PotPlayer 和 LAV Filters。
二者都是普通的 exe 安装包,双击启动即可,将安装路径设置到 Tools 文件夹,其他安装选项全默认。

3、安装 madVR,xy-VSFilter 或 xy-SubFilter。
二者都是插件,安装方法为:将压缩包解压至 Tools 文件夹中,右键点击各自的 install.bat,以管理员权限运行,若移动这些组件则需要重新安装。

我是按potplayer的路径,都放在里面了
installPath

PotPlayer 设置篇

1、 显卡卡驱动设置。

N 卡用户

打开 Nvidia 驱动面板,将红框中的动态范围参数调整至完全,蓝框的输出颜色深度调到10bpc或者8bpc(取决于显示器支持),如下图
001-N卡驱动设置.png
N卡驱动2.png

Intel 核显用户

将量化范围设为全范围:

IntelFullRange.png

AMD 显卡

新版设置界面,选择 Full RGB:
AMD_Full.png

CCC 旧版界面,同样选择 Full RGB:
AMDFullRange.png

2、PotPlayer 选项设置。

我们先用 PotPlayer 随便打开一个视频,按一下 Tab 键,调出 Potplayer 自带的 OSD 菜单,如下图。这是 Potplayer 的默认方案,读作 “a piece of shit”。接下来我们要调教它,关掉各种渣渣内置滤镜,以我们准备的各种外置滤镜代替之。
002-pot默认方案.png

蓝色框中的 Pot 内置解码器,我们要用 LavFilters 代替;
红色框中的视频渲染器,简称 EVR,是Windows 充话费送的渣渣,几乎所有名字中带有“影音”二字的垃圾播放器用的都是它;
橙色框中的部分,是 Pot 内置的视频处理滤镜弄出来的,不知道它怎么 PS 画面的,故需要消灭之。

(1)在播放界面点击鼠标右键-选项-播放,(快捷键F5)打开设置界面,开始调教 Pot 的进度条,将红框中的部分调整至如下图,其他选项也可参照图中改动。

002-调进度条.png

(2)切至滤镜选项卡,关闭 Pot 内置滤镜(最重要),防止 Pot 对视频进行瞎处理,操作如下图。

003-关闭Pot内部滤镜.png
如果没有关闭 Potplayer 内置图像滤镜,数据在传递给 madVR 前已经从 10-bit 砍成 8-bit 损失精度,madVR 内部再怎么精度高也是白搭。这一点 VCB-Studio 的旧版 PotPlayer 教程中最大的遗漏,它直接导致这片新教程的出现。

(3)展开滤镜选项卡,点击 源滤镜/分离器 分支,开始载入外挂 LavFilters。点击红框中的按键,管理滤镜和解码器。

004-添加外挂滤镜.png
点击下图红框中的搜索后添加,左边蓝框会出现一堆解码器;点击确定,加载 LavFilters 完成。
005-添加外挂滤镜2.png
005-添加外挂滤镜3.png
点击确定后上图界面关闭,自动回到源滤镜/分离器选项卡。带*的选项都是外挂的滤镜/解码器。将红框中的所有选项都换成 Lav Splitter Source;无法切换为 Lav 的就保持原状,参考下图
006-LAV分离器.png
接下来,视频解码器和音频解码器也如法炮制,所有能换成 Lav 的项目全部换成 Lav。
007-LAV视频解码器.png
008-LAV音频解码器.png

下一步,个人滤镜优先权,添加字幕插件 xy-vsFilter(即 DirectVobSub,通用) 或 xy-SubFilter(madVR专用)。以前者为例,操作如图。
010-字幕插件.png
010-字幕插件2.png
xy-vsfilter字幕插件优先级.png
xy-vsfilter字幕插件优先级2.png
优先级设置上,DirectVobSub (auto-loading version) 设为强制使用,负责外挂字幕;DirectVobSub 设为按优先级使用,负责内挂字幕。

建议使用 madVR 的同学用 xy-SubFilter,设置方法相同,效果会好一点,Bug 也少点,支持内挂图形字幕,不支持外挂图形字幕。

如果要自动载入字幕,一定要让字幕文件跟视频频文件的文件名相同。

以上二者均可渲染内挂和外挂文字字幕(ass 和 srt 等格式),但是不能渲染外挂图形字幕(SUP 和 PGS)。外挂图形字幕请使用 Pot 内置字幕插件。

(个人滤镜优先权这块可以实现一些额外功能,比如一些特殊特效代码必须使用的vsFilterMod;插帧用的SVP或AFM都需要在这里加插件,但是我强烈不建议折腾这些东西。它们会极大地增加bug概率,还会造成降低精度、撕裂、鬼影等无法修复的瑕疵,其副作用足以抵消我们为优化画质所做的所有努力。)

(4)切换至视频选项卡,设置默认视频渲染器,选择 madVR。

012-视频渲染器选择.png
madVR 的全称是 madshi Video Renderer,是 Windows 平台最强视频渲染器,调教得当的话效果媲美顶级蓝光机,当然消耗也不小。

屏幕 1920×1080 分辨率,则 GTX 960 / 1050 Ti 级别显卡足够体验 madVR 的所有好处;屏幕 2560×1440 或者 3840×2160 分辨率,GTX 970 / 1060 3G 级别显卡勉强可以享受所有好处,GTX 1060 6G 足够,GTX 1070 则绰绰有余。

(5)切换至 色系/属性 选项卡,设置 YCbCr<->RGB 规则,设为自动选择,如图。

013-色彩空间转换.png

(6)音频渲染器设置

根据一些文档叙述,WSAPI渲染器比 Default Direct SoundDevice 效果好,具有程序独占,抗干扰,延迟低的优点;建议关闭规格化,避免 Pot 擅自改变音量。操作方式如下:
014-音频渲染器选择.png
015-取消声音规格化.png

做完这一步,Potplayer 设置就完成了,记得点击应用和确定按钮,不然就白忙活了。

LAV 和字幕设置篇

本部分主要教如何切换视频、音频、字幕轨道,以及设置软解和硬解的方法。
随便打开一个视频,在播放界面点击右键-属性,打开此界面。点击橙色框就能进入视频/音频解码器设置界面。

009-如何调整解码器(右键-属性).png

(1)视频解码器 LAV Video Decoder 设置。LAV 的设置分为两套方案,A 方案应搭配 madVR 使用,B 方案搭配默认的 EVR(CP) 使用。

A:如果使用 madVR,橙色框中的 Output Format 勾选除了 AYUV 以外的所有选项;RGB Output Level选 PC;Dither Mode 选 Random。LAV 默认设置就是如此,如图所示。
LAV-all.png

B:如果使用 EVR(自动选择),橙色框中的 Output Format 只勾选 RGB24 选项;其他同上。(仅供需要省电或显卡性能不足者使用)
LAV-RGB24.png

为什么 madVR 和 EVR 勾选方式不同?

因为 madVR 能正确处理 LAV 解码出的所有数据,LAV 解码出的数据原封不动喂给 madVR 就是最好的,这是 madVR 被称作最强视频渲染器的主要原因之一。然而 EVR 只支持处理 8-bit 数据,LAV 解码出的 10-bit YUV 数据会被 EVR 直接砍成 8-bit YUV 进行处理,导致精度大幅降低,色带满天飞,这也是Pot 默认方案读作 a piece of shit 的主要原因之一;如果让 LAV 解码后将 10-bit YUV 转为 RGB24,也就是 8-bit RGB,再喂给 EVR 处理,可避免精度大幅损失。

渲染器 madVR 和 EVR 可以在 pot 的播放界面快速切换,方法是:右键-视频-视频输出设备。切换渲染器的同时,记得要修改对应的 LAV Video Decoder 设置。再次强调,A 方案配 madVR 使用,B 方案配 Potplayer 默认的 EVR 使用。

很多使用 madVR 的观众被这篇供非 MadVR 用户使用的教程 https://vcb-s.com/archives/4384 误导,只勾选了 RGB24,导致 madVR 没有接收到 LAV 解码出的正确的数据。

(2)硬解相关设置。

N 卡 GTX 950 / GTX 960 / GTX 1000 全系列、A 卡 4 系 5 系全系列以及 Intel 七代(Kaby Lake)处理器集成显卡可硬解 HEVC 10-bit YUV420 视频。

常见显卡都能硬解 AVC 8-bit YUV420 视频,所有显卡都不能硬解 AVC 10-bit 视频。接下来以 HEVC 10-bit YUV420 的视频进行示范。

CPU 软解 + madVR 示范,注意绿框中的 Active Decoder 和红框中的输出:
016-LAV解码器设置与HEVC-10bit-软解示范.png

蓝色和绿色框中是解码器选项,如果使用 CPU 软解,则选择 None;如果使用显卡 GPU 进行硬解,则选择 DXVA2 (copy-back) 或 DXVA2 (native),A/N 都可用,前者兼容性更好,后者更节省 CPU;如果使用英特尔核显,则选用 Intel QuickSync;NVIDIA CUVID 是 N 卡专用硬解方式,基本用不上。

DVXA2 (native)硬解 + madVR 示范:
017-LAV解码器设置与HEVC-10bit-硬解示范.png

红框中显示 dxva,实际上输出依然是 P010,橙框中的 Active Decoder 为 dxva2n,OK 表明显卡支持此硬解方式。DXVA2 (copy-back) 和其他硬解方式都类似。

解码方案优先级推荐:CPU软解 > DXVA2(copy-back) = Intel QuickSnyc > DXVA2(native) > NVIDIA CUVID (建议没事别用硬解,因为偶尔会出现 bug,况且大多数人也不缺这点 CPU 性能)

(3)音频解码器 LAV Audio Decoder 设置。仅有一项需要调整,勾选 Enable Mixing。

018-LAV音频解码器-混音设置.png

由于绝大部分人都使用双声道设备,所以遇到 5.1 声道音轨时,只有左/右两声道会被耳机/音响接收,其他声道都直接丢弃了。所以,一般来说我们应让 LAV 把多声道混流成双声道(Stereo)再输出;玩多声道音响的土豪请随意。

(4)字幕处理

我们已经在上面设置好了 xy-vsfilter 或 xy-Subfilter 字幕插件,所以要关闭 Pot 内置渣渣字幕插件,否则就会出现两行字幕的奇观,右键-字幕-取消勾选显示字幕,如图。字幕应该跟视频放在同一目录下,且与视频文件同名,会被自动加载,字幕由 DirectVobSub 或 xy-SubFilter 控制,而非 Potplayer。
020-关闭Pot内置字幕滤镜.png

(5)切换多字幕轨/多视频/多音轨

使用右下角的任务栏里 LAV 和字幕插件 DirectVobSub 或 xy-SubFilter 的图标。很多观众都不知道 VCB-Studio 以及其他压制组制作的 BD 往往含多条音轨,比如文件名中含 2flac、flac_aac、FLACX2 等字眼的 mkv,以及外挂 mka。这意味着视频带有多音轨,可能是 5.1,也可能是声优或是 staff 评论音轨,可以切换着使用。
020-如何切换字幕轨和音频轨(右下角任务栏).png

切换音轨也可以直接点击右键-声音-选择声音来实现,进行切换;视频轨同理,不过多音轨很常见,而多视频轨几乎见不到。
021-在potlapyer内切换音轨-02.png

madVR 调教篇

madVR 的核心优势有两个:

1、高精度的数据处理,避免画面失真,产生色带、锯齿等瑕疵;

2、高质量的缩放算法,在片源分辨率低于屏幕分辨率时,提供更清晰、更锐利的画面,算法甚至优于很多高级蓝光机。

madVR 功能强大,其调教也大有学问,本篇教程不再赘述 madVR 调教具体步骤,详情请见我们之前做过的 madVR教程: [VCB-Studio 科普教程 2] madVR 渲染器配置教程

如果教程也无法满足你的需求,欢迎有耐心、有基础者钻研:万年冷冻库 最强渲染器——madVR设置研究

以上,以 Potplayer 为基础的高质量播放器工具链设置完成,请尽情享受高清影视的乐趣吧!

关于一些问题的统一回复:

1、为什么使用 madVR 全屏时候会黑屏?

答:黑短短几秒是正常的,表明 madVR 正在切换至全屏独占模式(fullscreen exlucsive mode,简称 FSE ),这个模式有一些好处,比如防止画面撕裂。

如果你不喜欢 FSE 模式,可以在 madVR 中关闭它,具体操作为:取消勾选 madVR 的控制面板里的 rendering -> general settings -> enable automatic fullscreen exlucsive mode 选项。

2、为什么全屏 FSE 模式下点鼠标/切音轨/切换字幕/拉进度条画面会闪?

答:因为全屏模式就是给你看视频用的,任何操作都应该在按 Enter 键 或 点击鼠标中键 退回到 窗口模式 后再进行。

此外,全屏模式下完全可以用键盘轻松控制,比如 ←/→ 默认 后退/前进 5s;Ctrl + ←/Ctrl + → 默认后退/前进 30s;Ctrl + PageUp / Ctrl + PageDown 默认后退/前进 至上/下一章节,这些实用的快捷键都可以在 Potplayer 的设置里找到并定制。

3、为什么 EVR 和 madVR 切换时会卡死?

答:播放过程中, madVR 渲染器和 EVR 渲染器相互切换可能导致卡死,故建议尽量在暂停时切换。同理,任何切换字幕、音轨等操作,如果出现问题,应先暂停再操作;如果还不行,尝试关闭视频,重新打开。

4、为什么我按照教程设置还有这样那样的 Bug ?

答:最安全的方式是使用本教程文首提供的安装包,并按照教程从头重新设置 Potplayer。 Potplayer 本身就是个问题大户,版本号还那么多,导入 reg 文件导致的 Bug 也五花八门,无从下手。但按照本文的步骤从头设置,至少能将出问题的概率压到最低。我在许多台电脑上,按照本文的步骤设置过 LAV + Potplayer + madVR,从没出现过 Bug。

5、如何配合此教程的方案使用插帧/倍速播放/截图/录制等功能?

答:自己动手,丰衣足食,以上大多数功能可以由 Potplayer 本身实现,但不保证在使用 madVR 后还能用。本教程的目的是提供基本完美的视频播放功能,是为欣赏视频用的,不是拿来折腾的,不可能为各种细枝末节的需求做定制调整。更何况即使我们有心,播放器本身也未必能实现。

6、为何我的画面是上下颠倒的?为何我的 madVR 老是崩溃?

答:这两个问题大多是由 xy-vsFilter 造成的,因为 xy-vsFilter 存在不少 Bug,本教程以 xy-vsFilter 作为字幕插件纯粹是为了照顾无法使用 madVR 的用户。因此,只要你电脑能跑得动 madVR ,我都强烈建议改用 madVR + xy-SubFilter 的组合。各种字幕插件至今都是 beta 版,madVR 也是,如果出了问题,除了更新到最新的版本,也没什么更好的办法。实在不行那就用播放器自带吧,mpv、mpc-hc 和 mpc-be 自带的字幕插件尚且堪用;Potplayer 变黄前自带的字幕功能也勉强凑合,但变黄后就是一坨 shit。

那些播放器教程背后的知识

发表于 2018-02-07 | 分类于 多媒体

以下原文链接,非商业存个档学习
[VCB-Studio 科普教程 5] 那些播放器教程背后的知识

[VCB-Studio 科普教程 5] 那些播放器教程背后的知识

几乎一年前,我们写了一篇科普向的文章:http://vcb-s.com/archives/2726,意外地广受大家好评。很多读者在评论中表达了希望有后续科普的意愿,今天我们为大家带来这个系列的后续篇。

阅读本篇之前,请务必确保你基本理解了科普三(上文链接)的内容。如标题所示,本篇致力于讲述播放器相关的知识,而不是任何播放器安装教程。
这篇教程的目的是,为那些希望折腾一个更好播放器的观众,讲述一些平时你阅读的教程,不会跟你说的重要知识,来解答以下问题:

  • 播放器播放视频,是怎样的一个流程?

  • 硬解和软解的区别优劣在哪里?

  • 什么样的播放效果是最标准、最原汁原味的?

  • 为什么高级播放器教程全写的那么繁琐复杂,还特容易各种出错?

  • 为什么动漫压制特别喜欢用10bit,而且播放器动不动推荐madVR?

  • 不同精度在播放器中的标识是怎样?怎么判断播放过程是否对画质有折扣?

  • SVP/Reclock/XySubFilter是怎样插件?

  • 我应该怎样选择合适我的播放环境?

本教程将分以下模块详细叙述:

  1. 播放器的工作流程:分离,解码,渲染

  2. 硬解的定义、分类

  3. YUV->RGB转换过程中的细节

  4. 硬解的优劣与选择

  5. 图像格式的标识与查看方法

  6. 动漫画面区别于常规录制视频的特殊性

  7. 播放器软件的现状与分析

  8. 其他常见播放器配件简介

  9. 播放器配置学习的建议

1、播放器的工作流程:分离,解码,渲染

简单说就三个大步骤:分离、解码、渲染。

分离,指的是拿到媒体文件(MKV/MP4/MKA)等,先收集相关的文件(包括外挂音轨、字幕),然后将所有轨道拆开,拆分成单独的内容。视频流、音频流、字幕、章节信息,等等。负责执行分离的模块滤镜,叫做分离器(splitter/demuxer)。

当同样类型的轨道不止一条的时候(比如多音轨),分离器还负责挑选其中的一条。通常同类型多轨道,会有一条轨道被设定为“默认轨”(比如多音轨MKV一般以主音轨为默认),你想选择副音轨,你就需要在分离器中手动切换。很多播放器会在自己的界面中提供音轨/字幕切换的功能,其实也是间接利用分离器实现的。

分离器现在能用的基本上只有LAV/ffmpeg了(这俩几乎可以算一家),以前还有个Haali,然而停止更新已久,不能适应HEVC时代了。

分离器一般不耗费运算性能。因为它只是简单地收集、拆分和选择。

解码,指的是将分离器丢来的各种原生压缩格式,比如H264/H265的视频,FLAC/AAC的音频,解码为非压缩的格式,比如视频是YUV/RGB(相当于bmp),音频是PCM(相当于wav),然后丢给下游模块。负责解码的模块滤镜称为解码器(decoder)。常见的有LAV/ffmpeg, ffdshow(同样停止更新了)……

当解码器能完全解码一个轨道中所有有效信息的时候,我们成为完全解码(现在绝大多数情况是如此),否则称为不完全解码。比如说,早期一些显卡的硬解,不能完全处理H264视频流的所有,解码出的画质有折扣;又或者DTS-HD MA解码器开源之前,基于ffmpeg/lav等解码器只能解码出部分信息,导致音频是有损的。

解码出来的格式,都需要加上精度的度量。比如说10bit 视频完全解码后是YUV 10bit,8bit视频是YUV 8bit,16bit flac格式是PCM 16bit整数,aac是PCM 32bit浮点。麻烦在于,解码器下游的模块不见得能照单全收。比如说以前播放器就不支持10bit YUV丢给下游,解码器只好转为YUV 8bit(后来madVR之所以是一个极大的提升,就是因为madVR基本上全部通吃)。同理;很多声卡能支持24bit整数PCM已经是极限,所以32bit浮点的PCM需要转为24bit整数。

如果解码器可以将最原始的数据,或者更高精度(比如有时候为了方便,将10bit转为16bit)输出给下游,我们称为全精度输出;否则,解码器会试图降低精度输出,我们称为低精度输出。少数时候,我们会让解码器做一些转换(比如vcb-s新播放器教程中,让lav解码器做YUV->RGB的转换),我们称为转换输出。

解码器,特别是视频解码器,往往成为大量消耗运算资源的地方。这个问题在H264早期非常严重,那时候的主流CPU很难负担720p/1080p的高清解码,能耗巨大,移动平台尤其如此。所以才催生了各种硬件加速和硬件解码,并逐渐成为一个规范标准。

渲染,指的是将解码后的数据,在pc硬件上(显示器、扬声器)进行播放。负责渲染的模块我们称之为渲染器(Render),视频渲染器主流有EVR(Enhanced Video Render, 微软送的)以及madVR(madshi Video Render)。

音频渲染器一般都是系统自带的(同样是微软送的),也有可以自定义的。比如MPC播放器有MPC Audio Render,可以支持类似wasapi输出等其他功能。

因为显示器是RGB显示,而解码后的视频多为YUV格式,渲染器一般也需要负责将YUV转换为RGB,并保证输出的图像大小跟播放窗口吻合。

多数播放器自带的滤镜(mpc/pot都有很多调色之类的功能),显卡的加成,以及SVP,都作用于解码器和渲染器中间。它们接过解码器解码的数据,对其进行处理,然后将处理后的数据送给渲染器。因为渲染器是需要借助显卡进行图形运算,YUV数据基本上需要先进入显存,所以显卡可以检测到丢来的YUV数据,对其进行“优化”。同样需要当心的是,这些滤镜和处理,往往入口精度低,处理精度也低。导致的后果就是解码器被迫低精度输出,给这些滤镜低精度处理,从而大幅降低视频精度,导致色带色块问题。

字幕的加载可能在渲染器前(将字幕信息整合进YUV/RGB数据给渲染器),也可能在渲染器后(播放器来将字幕整合入生成完毕的RGB图像)。

多数解码包的配置界面,主要就是让你选择分离器、解码器和渲染器的:
pc5
如上图,上方就有让你选择视频渲染器,然后下方左右分别是针对不同文件格式的分离器,以及针对不同媒体格式的解码器。

2. 硬解的定义与分类

如上文所说,硬解是为了缓解高分辨率新编码面世初期,CPU不堪重负的解码压力,而诞生的技术。如果说软解的定义是:利用CPU通用运算能力,进行解码,那么硬解的定义可以这么说:不利用CPU通用运算能力,而是依赖其他集成电路,无论是否特制,来进行解码。

更古老的时候,有些显卡没办法进行完全解码,只是帮助计算部分解码过程中的运算,那么可以归为“硬件加速”。估计Intel下一代CPU“混合加速HEVC解码”也是一样的道理。

硬解现在比较常见的是以下种类:

DXVA(DirectX Video Acceleration),比较古老的方案了。Windows XP以及之前系统上流行的。上古ffdshow的硬解就是利用DXVA。DXVA规范下容易出现不完全解码,导致画质降低。Vista以后,渐渐地被抛弃。

DXVA2,目前主流的硬解方式。主要由GPU来实现,但是并非利用GPU的流处理器,INA三家都是使用了单独附在GPU芯片上的一块专职电路来完成。GPU硬解能力往往不与显卡游戏性能相关,而与搭载的专职电路先进与否相关。典型的就是GT610,它是NVIDIA第一款能硬解4K视频的GPU,同时代其他GTX650/GTX580什么面对4K视频只有傻眼的份儿,就因为它的GPU塞入的专职电路,是刚开发出最先进的一款(代号为VP5,其他同时代的都是VP4)。

使用DXVA解码,都需要先将视频数据(压缩的格式)传输到显存中,然后再让GPU进行解码。

DXVA2有两种实现方式:native和copy-back。区别是解码后的数据是否还要传回内存。

native选择不传,直接丢给同样依赖GPU工作的渲染器,数据从头到尾都在显存中。而copy-back选择传,数据会传回内存,一番处理后再传回显存,让渲染器工作。native的输出必须为YUV 8bit,而copy-back则可以为10bit。

之所以需要有copy-back这么个传来传去的过程,就是因为有些滤镜,比如SVP,比如LAV的转格式,必须依赖CPU+内存进行工作。不传回来没办法继续处理。copy-back保证了硬解的流程类似软解,可以不漏下任何后处理。而代价是传来传去必定降低性能,增加能耗。需要注意的是,即便用native,也可能导致解码后的数据被“优化”,因为有些处理,包括播放器、显卡驱动带的那些,是可以完全作用在GPU环境中的。

除了DXVA2,还有两种特殊的硬解:Intel Quick Sync, 和NVIDIA CUVID。如同名称所示,它们是Intel和NV的专属。

Intel Quick Sync是集成在CPU中的逻辑电路承担的。注意的是这玩意并非隶属于Intel的集显,而是CPU的直属。它直接读写内存,运行表现和软解非常类似。Intel Quick Sync堪称速度快,能耗低。

NVIDIA CUVID,是基于NV自己的接口,写的一个类似DXVA2(copy-back)的升级版。

硬解的模式可以在LAV Decoder的设置中选择:
banner26.jpg
红框的下拉框可选None(软解),CUVID,QuickSync,DXVA2(native 和 copy back)。

每选择一个模式(除了None),蓝框会显示一个单词:

Active:当前正在使用这种模式解码

Available:应该可以使用这种模式

Not Available:不支持使用这种模式

绿框当中则是显示当前在使用哪个解码器。如果是软解,显示avcodec,否则显示类似dxva2cb, dxva2n等标示。

碰到没办法开启硬解,比如设备不能正常工作,或者碰到10bit AVC这种不支持的,那么自动转为软解。

3、YUV->RGB转换过程中的细节

将解码器输出的YUV格式,转为RGB,并且缩放到播放窗口输出,是视频渲染器的职能。可以说,如果解码过程是完全解码,也不主动添加播放器调校和驱动增强,渲染的环节决定了最终成品的画质。造成画质区别的可以说就三点:缩放算法,运算精度,和抖动算法。任何试图优化渲染器效果的尝试,都应该从这三个方面着手。

缩放算法造成的区别,比较好理解。例如原图(150150):
kanade.png
用双线性算法(上,多数播放器默认算法)和nnedi3(下)放大到272
272像素:
19867d.png
20153.png

不同算法造成的效果肉眼可见。注意上图中随处可见的锯齿,以及细线的模糊。

精度,是指运算的过程中,参与运算的数,有效位数的高低。在计算机中表现为使用怎样的格式来进行,8bit/16bit/32bit整数,16bit/32bit浮点。精度不足的表现在上篇教程中已经有展示,不做赘述,然而还是提醒一句:千万不要以为显示器是8bit,就认为8bit 整数 的片源精度/处理精度是足够的。

另外,RGB处理相对YUV处理,精度要求相对较低;或者说,RGB处理相比较,精度稍低带来的影响不明显。(不幸的是多数时候处理的数据都是YUV,然后根据水桶原理……)播放过程中,应该尽量减少RGB-YUV互转的次数,每一次转换都要做一次计算与取整,都会导致实际精度降低。

抖动算法(Dithering Algorithm),通常出现在高精度转低精度中。在数字图像高转低处理中,全部四舍五入不见得是好习惯。抖动算法通过科学的添加噪点,来掩盖精度的不足。比如说原图(RGB24,即RGB 8bit):
output0.png
分别用四舍五入(上) 和 Floyd–Steinberg 抖动算法(下),将此图转为RGB16(RGB分别为5bit,6bit和5bit,早期windows桌面的“16色”,区别于RGB24的“真彩色”)
output00e38b.png
output012c78.png

可以看出,使用抖动算法的图片较好的掩盖了精度不足引起的色带和偏色问题。在YUV 和 RGB的运算过程中,如果出现高精度转低精度,是否使用抖动,使用的抖动算法如何,也会决定输出效果。

现在,我们来模拟一下渲染器的工作流程,并用蓝色标注出可能造成画质差别的地方:

1、渲染器从解码器那里获取YUV数据。注意拿到的数据可能是全精度,也可能是降精度,取决于渲染器接口类型;

2、播放器和显卡驱动可能会试图“优化”画面;

3、如果不是YUV444格式的,渲染器会先将UV平面放大到Y平面的大小。这个步骤称为Chroma upscaling;

4、将YUV444的数据,转为RGB。转换的过程势必需要浮点运算(YUV->RGB一些参与运算的常数是浮点数);

5、播放器或者渲染器将RGB用特定的算法缩放到播放窗口大小。这个步骤称为Image Upscaling(图像放大)/Downscaling(图像缩小);

6、因为4的步骤中,必须以浮点数运算,而输出结果一定是RGB 8bit整数,因此输出之前必须有一个高转低的过程。

2~6每一步都涉及数字运算,因此有运算精度的区别。

问:什么样的渲染器,什么样的输出画面是标准的、完美的?
答:没有。因为运算精度总可以无限的高,缩放算法也永远有提升的空间,所以视频播放不存在“标准、完美”一说;只有相比较而言的好与差,以及在人眼识别程度内的“接近完美”

问:有哪些渲染器能“接近完美”的处理以上所有情况?
答:只有madVR。

问:Windows充话费送的那个EVR,默认情况下有啥不好?
答:1、接口精度低,强迫YUV 8bit/RGB 8bit的输入;2、缩放算法默认是平庸的双线性;3、运算精度较低,默认只有8bit整数和16bit浮点数;4、抖动算法有,较为单一和固定;5、如果输入的是YUV数据,EVR会任由播放器和驱动乱来。

问:我们能怎么拯救EVR?
答:1、因为RGB对精度要求不敏感,而且输入RGB后,驱动和播放器基本没办法插手,所以设法永远输入RGB 8bit,不让YUV数据经过低精度处理;2、让LAV解码器来做YUV->RGB。LAV可以以32bit浮点的高精度、双立方的UV放大算法、随机抖动算法,较高质量的完成转换;3、图像缩放算法手动设置为更高级的双立方。

问:听上去不错,我们应该怎么操作?
答:参见http://vcb-s.com/archives/4384或者http://vcb-s.com/archives/4407

所以,如果你使用的是madVR渲染器,你应该允许LAV输出它默认设置的那些格式,YUV/RGB。LAV会以全精度输出YUV给madVR进行处理;如果你使用EVR渲染器,你应该永远只允许LAV输出RGB 8bit。

RGB 8bit 包括RGB24和RGB32。RGB32多一个透明层通道,看似带了个没用的东西,但是因为计算机更喜欢2的次方,所以部分运算下RGB32比RGB24快。在视频播放中,这两个格式几乎完全等同;互转也人畜无害(加一个空的透明度通道 vs 去掉透明度通道)。

之前基于EVR CP教程中,之所以pot推荐RGB24输出,而mpc推荐RGB32输出,是测试的结果。这样设置播放器不会再多一次转换(虽然就算转换了也没啥)

4、硬解的优劣与选择

绝大多数vcb-s的教程,都让大家不要开启硬解,就算开启,优先使用DXVA2(copy-back),这里我们做一个详细的解释。

首先考虑一个问题:什么样的视频能被硬解?

8bit AVC可以被各种显卡硬解;然而8bit AVC格式的软解压力小的可怜,以vcb-s常发的24fps 1080p的视频算,现在CPU软解,占用率普遍不到5%。

10bit AVC没有能硬解的。(所以10bit版炮姐时代,试图硬解的洗洗睡吧。)软解,解码压力尚可,不是很可怕,24fps 1080p的视频,现在的cpu大约10%

8bit HEVC现在最新显卡普遍能硬解;然而因为8bit x265的缺陷(或者说8bit x264的优越性),我们发现这玩意表现多数还不及8bit AVC,所以vcb-s从来不用;相对而言,它的解码压力也不大,大致相当于10bit AVC。

10bit HEVC,目前只有NV的GTX950和GTX960支持硬解。它的软解压力算是比较大,现在主流的CPU占用在20%左右;对于上古CPU或者一些低端笔记本CPU,流畅解码会比较吃力,特别是60fps的特典。对于将来的4K 60fps,现在桌面4核心CPU基本上完全无力软解。

能硬解的视频必须是YUV420格式。

分析完毕了,你觉得自己需要硬解么?

如果你没有GTX960/GTX950,你也基本碰不到1080p 60fps乃至4K的8bit HEVC,那么你只能去硬解8bit AVC,省那么5%不到的CPU占用率——真有这个必要么?软解吃力的硬解解不了,硬解解得了的软解解的飞起,那我们为什么要冒着各种潜在风险去开硬解呢?

好吧,就算你说我真有理由要开硬解:我有GTX960/950,我的CPU真的太烂……我们来分析下不同情况下,硬解应该怎么开。硬解设置跟你使用的渲染器有关:

如果你使用madVR,通常是不建议你开硬解的。众所周知madVR会消耗大量显卡运算,因此没必要再去把大量数据塞进GPU和显存,跟madVR抢夺资源。让CPU分担解码,让GPU专心跑madVR,是比较推荐的做法;

如果你使用GTX960/950硬解10bit HEVC,请务必设置为DXVA2(copy-back),这是现在唯一可以开启10bit HEVC硬解的模式;

其他情况下,如果你真的非要开硬解搭配madVR,建议顺序(保证你硬件可用): Intel QS, DXVA2(native), NV CUVID, DXVA2(copy-back),其实用哪个都没有太多关系,主要的功耗消耗点在madVR。

如果你使用EVR CP(调节过缩放算法),希望追求较高质量的播放,你首先要排除的是DXVA2(Native)。因为这种模式下,LAV会直接输出YUV 8bit给显卡,哪怕强制规定了输出只能是RGB。用DXVA2(copy-back)是可以的;这种模式下,解码后的数据将回传给CPU,继续做高质量转RGB的后续操作。

如果你使用GTX960/950硬解10bit HEVC,请务必设置为DXVA2(copy-back),理由同上,并且也需要强制RGB输出。

其他情况下,建议顺序: Intel QS, NV CUVID, DXVA2(copy-back)

所以不难理解为什么之前教程我说了,要开硬解请用DXVA2(copy-back)。这种软解流程、硬解运算的泛用性模式,是最人畜无害的,哪怕这种模式折腾程度,导致在性能和功耗上大多是得不偿失。

追求最大性能的,特别是用来对付那些能够被硬解的高清病毒的,请使用EVR默认,搭配DXVA2(Native)播放。这样效率应该是最高的,各种专治8bit AVC 4K的高清病毒。只不过这种做法会损失画质,因此不建议日常使用。

5、图像格式的标识与查看方法

在播放器中,不同格式、不同精度的图像,有着规范的定义和标号。这一点可以在LAV的设置界面很清楚的看到:
20154.png
其中蓝色部分标示的这些是最常见到的,主要是YUV 420的不同精度,以及RGB格式(注意16bit RGB,即RGB48,在现有播放器体系下还没有实装,所以现在播放器中的RGB基本就是RGB 8bit)

使用DXVA2(Native)硬解的时候,输出是DXVA,也是YUV420 8bit。

RGB格式除了上文所说的RGB32和RGB24,播放器中还有XRGB和ARGB的标示,也都是一回事儿。

Potplayer中观察方法,可以用tab键显示:
banner261.jpg

potplayer会给出视频解码器(图中是LAV)

解码器输入的格式是HVC1(HEVC),输出是RGB给渲染器。YUV->RGB的过程完全是LAV处理。

渲染器是EVR CP,渲染整个过程,格式都是RGB,没有转回YUV。需要注意的是你必须关闭pot自带的内置滤镜(按F5,进入”参数选项”设置。 2、点击“滤镜”,将右边的”内置图像处理滤镜设置”激活条件设置为:”不使用”),否则potplayer一定会自作主张转回YUV的。

缩放算法是Lanczos 3。(注意如果你播放画面跟视频画面相同,比如你在1080p的显示器上全屏播放,缩放算法会显示临近采样,这是正常的)

MPC-HC/MPC-BE中,按Ctrl+J可以调出类似的信息:(再按1~2次取消)
20155.png
红框中勾选的,Formats表示渲染过程中格式变化,从始至终都是RGB;

Video Size给出了原始尺寸和播放尺寸,以及使用的缩放算法(双立方 A=-0.6)

Decoder则是解码器;输出是RGB。

通过这样的查看方法,你可以知道你的播放器工作流程,以及设置是否按照预期。

6、动漫画面区别于常规录制视频的特殊性

一直以来都有这样的说法:“10bit, madVR这些东西都是那些压动漫的人弄出来的歪门邪道,我是看不出这些东西在电影上有个P用。”

其实吧,这还真不是这群人眼力不好或者装睡不醒。区别于录制视频,比如电影之类的,动漫、CG等有着自己的特殊性。总结起来就两点:1、噪点少,2、线条非常突兀。

视频拍摄,限制于器材水准,噪点是不可避免的,在后续制作等过程中也难以完全去除。而动漫天生可以0噪点,动漫中的噪点更多是数字图像处理中主动加上去的。噪点的一大作用就是极大地降低视频处理和压制,对于精度的需要。说的简单点:高噪点的视频不怕低精度,反之亦然。

怎么理解这个概念呢?我们借助一个简化的图片来演示。假设我们有一条平滑、高精度的曲线(这是y=1/x在[10,30]上的图):
19867df6ec8.png

现在,我们把所有函数值,四舍五入到小数点后三位数:
19867d0c8de.png
降低精度的效果很明显,我们现在的图看上去跟楼梯一样,出现了明显的”断层”。表现在视频中,这种断层就是色带。同时值得注意的是,越是平坦、变化小的地方(就是之前科普中的”平面”),色带表现越严重。

现在,我们模仿给图像加噪点,来给这个函数加一个小幅度(约为1%)随机抖动:
19867d90730.png
然后我们也把它的精度限制为小数点后3位:
19867d5bb28.png
可见,这一次精度降低,图像似乎没有受到太多影响,精度降低造成的阶梯状效果也很不明显。表现在数字图像处理中,意味着噪点重的图片,在降低精度的时候收到的影响很小。

这就是为什么那些致力于改善精度的提升,对于电影等视频几乎没有用——播放过程的精度低怎么了;能有什么视觉影响?

类似的现象,噪点会使得人眼对图像锐利度等差异不敏感,或者说,缩放算法造成的区别,变得不太可见。以之前的图为例,假如为两幅图都加上强度相同的噪点:
20151.png
20152.png

区别已然几乎不可见。注意噪点是如何帮忙掩盖拉升过程中的锯齿等瑕疵,并加入虚假的高频信息,让图像看上去细节很丰富。这还是应用在线条/平面非常分明的动漫;换作电影,这样的差异只会更不起眼。

小结一下,当有噪点存在的时候,主打高精度、优秀缩放算法的播放器,优势将不再明显。从另一个方面讲,面对较少噪点、较为突出线条的动漫,对播放器的精度和缩放算法提出的要求就很高。编码器也是一样的道理,动漫非常需要10bit x264/x265这样原生高精度的编码器来提升画质。

因此,再面对本节开头的说法,不需要反驳,那是很自然的(摊手)。

问:既然加噪点可以有效避免精度降低,为什么在动漫压制中不用这个方法呢?

答:噪点作为一种高频信息,需要浪费成倍的码率。在今天10bit编码可以不增加(甚至减少)码率完美解决问题的前提下,我们为什么要用10年前的理解呢?

PS: 10年前只有8bit编码器的时候,主动加噪确实是很常见的防色带、去色带手段。在今天商业性蓝光编码器只有8bit精度的限制下,很多动漫蓝光后期也是通过加噪点解决的(Sony那高大上的“SBMV技术”的核心)。然而,蓝光可以不惜码率,Rip不行,除非你是Yousei。(所以Yousei的Devil-Jin至今用着这种手段)

7、播放器软件的现状与分析

接上文分析。面对占绝对多数的电影观众,现有的播放器,pot/mpc默认,已然足够好了。再好的设置能带来的观感提升几乎没有,还不如在什么一键增强,左眼效果,以及在线字幕、弹幕上下功夫。

面对多数动漫党,稍微修改一下基于EVR CP+LAV的播放设置,也能达到很满意的效果,很平衡的兼顾画质、性能与稳定性。所以如果你不求折腾(还把这么长的教程看到这里,真是辛苦你了),建议使用vcb-s最新写的两篇64bit播放器教程。

如果你真的欲求不满,那么你就可以试着接触madVR,SVP这些东西。但是有一点需要提醒的是:这些纯粹由fans开发的东西,甚至包括mpc/pot这些软件,是高度不可靠的。哪怕所谓的“稳定版”,出bug的几率都很高。(更别提现在madVR一直都是“测试版”,版本号还在0.x)MadVR至今有个问题,就是它所在的目录路径不能有中文。这个问题存在几年了,作者压根不屑于,或者说,抽不出精力去修复它——你见过几个正儿八经的软件不支持安装目录有中文?!

更恐怖的是,高质量播放依赖的组件数量庞大,而彼此之间缺乏系统性的联系测试。开发者往往是各自测试各自的,没有组织、没有公司说作为一个整体来调试一套方案。当播放软件趋于复杂,组件数量增多,功能强化,出错的概率指数级上升。一个基于potplayer+madVR的播放方案,不考虑音频,涉及到以下可能出问题的地方:

potplayer本体, LAV分离器,LAV视频解码器,madVR渲染器,操作系统,显卡和显卡驱动。

假设每一个组件出错的平均概率是3%,求问这一套方案正常运行不出错的概率是多少?1-0.97^6=83%。

也就是说,平均5个人里面,就有一个人用这套方案出错。出错的理由往往很难查到,每个人都有每个人的原因。

(举个我自己的例子,虽然我写的教程基于mpc-hc,但我自己在用mpc-be。因为对于mpc-hc,我设置让EVR渲染器使用双立方缩放,mpc-hc始终都使用的是最朴素的双线性,导致缩放效果很差(对我来说)。各种途径查错无功而返,最终换mpc-be问题解决。)

所以以后请别问我为什么不写madVR+SVP+Reclock+XySubFilter这些高端货的教程,更别出了错问我错在哪里、怎么解决——臣妾做不到啊!

8、其他常见播放器配件简介

除了madVR,其他播放器折腾一般还有这些配件:

SVP(Smooth Video Project)比较众所周知了,它是一个插值平滑软件。本身依赖avisynth开发,通过ffdshow/ffdraw来加载,作用在解码器之后,渲染器之前。SVP只能支持YUV420 8bit输入输出。

SVP的性能消耗非常可观,特别是开启OpenCL之后,如果再开启madVR(接EVR CP容易导致精度问题,这时候可以手动在ffdshow/ffdraw中加噪点来缓解),对显卡的性能和驱动稳定性都是考验。尽管如此,SVP的插值平滑带来的观看提升也是非常可观的,强烈建议madVR的倍帧满足不了、同时又有很强配置的观众们爬文安装。

XySubFilter,是目前最先进的字幕插件,对高级字幕特效的支持,渲染的质量,性能的优化,对高精度播放以及madVR的配合都做得很到位。如果你患有字幕强迫症末期,建议去折腾一下这个插件。

Reclock,一个致力于改善播放视频帧率不稳定的插件,不过多数人用它的目的可能还是为了它的wasapi输出。实际表现完全聊胜于无,特别是wasapi现在mpc自带的audio render就内置了,而且Reclock没有64bit版,因此不建议折腾。

9、播放器配置学习的建议

对于想自学高级播放器设置的同学们,教程总是不缺的,网上一搜一大堆,各大论坛什么的置顶帖,万年冷冻库,等等。写的比vcb-s现有几篇教程更新、更详细、更高端的比比皆是,也都可以作为很不错的教程。然而我一直认为,这些教程只是授人以鲤,或者授人以鳊、鲢、鳙……,导致的结果就是来一只鲫,或者给你个渔网让你按照自己喜好捞一只,很多人一下子就傻眼了。

这也是我写这篇教程的初衷,讲述一下现在网上林林总总的教程,不会跟你说的很多细节与知识。有的人madVR设置玩出了花,结果不知道检查pot内置的ffmpeg解码器,会把YUV420 10bit 降低精度+瞎转换 为YUV422 8bit丢给madVR,然后又说自己看不出区别……这折腾的意义何在呢。

学习播放器配置,有这么几条原则,是我希望分享给大家的:

1、实事求是。不要盲目的去折腾,也不要为了心理安慰去折腾。一套更好的方案,只有你确实感觉到了提升,并且这个提升在你心理满意度上,足够抵消麻烦,才值得你去升级。比较的过程中,相信自己的眼睛,而不是相信别人的说教。比如说我真不推荐笔记本用户折腾任何顶级缩放算法——那么小个屏幕你能看出点啥?教程里说出花的放大算法跟你有几毛钱关系?

2、循序渐进。先把一套简单基础的方案弄好弄懂,再去学习和尝试更好的方法。对于新的插件,你要尝试测试它们在你机器上的表现;对于别人的设置,设法了解他这么推荐的原因,以及这个原因是否适用于你。最典型的,很多人用着madVR问我,你在新教程里教我们LAV只勾选RGB,我要改么?看了这篇教程你应该知道要不要改与背后的原因了吧。

3、量力而行。播放器越高级,组件越多,往往性能消耗越大,出错概率也越高,同时收益越少。学会放弃与妥协,毕竟,你看的是片子,不是播放器组件和参数。

视频格式基础知识

发表于 2018-02-07 | 分类于 多媒体

看连接内容好了,我只是存个档

[VCB-Studio 科普教程 3] 视频格式基础知识

[VCB-Studio 科普教程 3] 视频格式基础知识

这本来是群内写给队友做入门知识学习的,然后觉得挺适合改改贴出来向大家科普,所以就有了这篇教程。之前的两篇播放器教程可以算 1 和 2 吧。

本教程意在讲述一些视频音频制作的基础知识和术语,适合不了解压片原理的收片党们自学。它可以比较详细地回答以下常见的问题:

  • MP4/MKV 这些格式有什么区别?哪个画质好?

  • 视频的码率是怎么算的?为什么同样是 1080p 的视频,有些体积大有些体积小?

  • 视频储存的图像信息是什么格式的?跟显示器一样的红绿蓝么?

  • 8-bit/10-bit 到底指的什么?为什么说 8-bit 显示器还有必要看 10-bit 视频?

  • YUV420/444 这些标示到底什么意思?哪个好?

  • 线条,平面,纹理这些到底是什么意思?视频为啥还有高频低频?

  • 码率越高的视频画质越好么?

本教程将分以下模块详细叙述:

  1. 封装格式(MP4/MKV…)vs 媒体格式(H.264/FLAC/AAC…)

  2. 视频的基础参数:分辨率、帧率和码率

  3. 图像的表示方法:RGB 模型 vs YUV 模型

  4. 色深

  5. 色度半采样

  6. 空间上的低频与高频:平面、纹理和线条

  7. 时间上的低频与高频:动态

  8. 清晰度与画质简述

1、封装格式(MP4/MKV…) vs 媒体格式(H.264/FLAC/AAC…)

MP4+MKV是你下载的视频文件最常见的种类。这些文件其实类似一个包裹,它的后缀则是包裹的包装方式。这些包裹里面,包含了视频(只有图像),音频(只有声音),字幕等。当播放器在播放的时候,首先对这个包裹进行拆包(专业术语叫做分离/splitting),把其中的视频、音频等拿出来,再进行播放。

既然它们只是一个包裹,就意味着这个后缀不能保证里面的东西是啥,也不能保证到底有多少东西。包裹里面的每一件物品,我们称之为轨道(track),一般有这么些:

视频(Video): 一般来说肯定都有,但是也有例外,比如mka格式的外挂音轨,其实就是没视频的mkv。注意我们说到视频的时候,是不包括声音的。

音频(audio):一般来说也肯定有,但是有些情况是静音的,就没必要带了。

章节(Chapter): 蓝光原盘中自带的分段信息。如果文件带上了,那么你可以在播放器中看到带章节的效果:

  • potplayer右键画面,选项-播放-在进度条上显示书签/章节标记

  • mpc-hc 右键画面,选项-调节-在进度条显示章节标记

字幕(Subtitles):有些时候文件自带字幕,并且字幕并非是直接整合于视频的硬字幕,那么就是一起被打包在封装容器中。

其他可能还有附件等,不一一列举。每个类型也不一定只有一条轨道,比如经常见到带多音轨的MKV。

每个轨道,都有自己的格式。比如大家常说的,视频是H.264,音频是AAC,这些就是每个轨道的格式。

视频的格式,常见的有H.264(可以细分为8bit/10bit),H.265(当前也有8bit/10bit之分),RealVideo(常见于早期rm/rmvb),VC-1(微软主导的,常见于wmv)。基本上,H.264=AVC=AVC1, H.265=HEVC。

音频的格式,常见的有 FLAC/ALAC/TrueHD/DTS-HD MA这四种无损,和AAC/MP3/AC3/DTS(Core)这四种有损。

MKV vs MP4,主要的区别在于:

  1. MKV支持封装FLAC作为音频,MP4则不支持。但是MP4也可以封装无损音轨(比如说ALAC,虽然普遍认为ALAC的效率不如FLAC优秀)
  2. MKV支持封装ASS/SSA格式的字幕,MP4则不支持。一般字幕组制作的字幕是ASS格式,所以内封字幕多见于MKV格式
  3. MP4作为工业标准,在视频编辑软件和播放设备上的兼容性一般好于MKV。这也是vcb-s那些为移动设备优化的视频基本上选择MP4封装的原因。
    除此之外,这两个格式很大程度上可以互相代替。比如它们都支持封装AVC和HEVC,包括8bit/10bit的精度。所以MP4画质不如MKV好,这种论断是非常无知的——它们完全可以封装一样的视频。

为什么会有这样的分歧,就是历史原因了。MKV是民间研发,为了代替古老的AVI,从而更好地支持H264,它开发和修改的灵活度使得它可以兼容flac/ass这类非工业标准的格式;而MP4则是出生豪门,作为工业标准,替代更古老的MPG,作为新一代视频/音频封装服务的。

2、视频的基础参数:分辨率,帧率和码率。

视频是由连续的图像构成的。每一张图像,我们称为一帧(frame)。图像则是由像素(pixel)构成的。一张图像有多少像素,称为这个图像的分辨率。比如说1920×1080的图像,说明它是由横纵1920×1080个像素点构成。视频的分辨率就是每一帧图像的分辨率。

一个视频,每一秒由多少图像构成,称为这个视频的帧率(frame-rate)。常见的帧率有24000/1001=23.976, 30000/1001=29.970, 60000/1001=59.940, 25.000, 50.000等等。这个数字是一秒钟内闪过的图像的数量。比如23.976,就是1001秒内,有24000张图像。视频的帧率是可以是恒定的(cfr, Const Frame-Rate),也可以是变化的(vfr, Variable Frame-Rate)

码率的定义是视频文件体积除以时间。单位一般是Kbps(Kbit/s)或者Mbps(Mbit/s)。注意1B(Byte)=8b(bit)。所以一个24分钟,900MB的视频:

体积:900MB = 900MByte = 7200Mbit

时间:24min = 1440s

码率:7200/1440 = 5000 Kbps = 5Mbps

当视频文件的时间基本相同的时候(比如现在一集番大概是24分钟),码率和体积基本上是等价的,都是用来描述视频大小的参数。长度分辨率都相同的文件,体积不同,实际上就是码率不同。

码率也可以解读为单位时间内,用来记录视频的数据总量。码率越高的视频,意味着用来记录视频的数据量越多,潜在的解读就是视频可以拥有更好的质量。(注意,仅仅是潜在,后文我们会分析为什么高码率不一定等于高画质)

3、图像的表示方法:RGB模型 vs YUV模型

光的三原色是红(Red)、绿(Green)、蓝(Blue)。现代的显示器技术就是通过组合不同强度的三原色,来达成几乎任何一种可见光的颜色。图像储存中,通过记录每个像素红绿蓝强度,来记录图像的方法,称为RGB模型 (RGB Model)

常见的图片格式中,PNG和BMP这两种就是基于RGB模型的。

比如说原图:
1111
分别只显示R G B通道的强度,效果如下:
111
1112
1113
三个通道下,信息量和细节程度不一定是均匀分布的。比如说可以注意南小鸟脸上的红晕,在3个平面上的区分程度就不同——红色平面下几乎无从区分,造成区别的主要是绿色和蓝色的平面。外围白色的脸颊,三色都近乎饱和;但是红晕部分,只有红色饱和,绿色和蓝色不饱和。这是造成红色凸显的原因。

除了RGB模型,还有一种广泛采用的模型,称为YUV模型,又被称为亮度-色度模型(Luma-Chroma)。它是通过数学转换,将RGB三个通道,转换为一个代表亮度的通道(Y,又称为Luma),和两个代表色度的通道(UV,并成为Chroma)。

举个形象点的例子:一家养殖场饲养猪和牛,一种记数方式是:(猪的数量,牛的数量)

但是也可以这么记录:(总数量=猪的数量+牛的数量,相差=猪的数量-牛的数量)。两种方法之间有数学公式可以互转。

YUV模型干的是类似的事儿。通过对RGB数据的合理转换,得到另一种表示方式。YUV模型下,还有不同的实现方式。举个用的比较多的YCbCr模型:它把RGB转换成一个亮度(Y),和 蓝色色度(Cb) 以及 红色色度(Cr)。转换背后复杂的公式大家不需要了解,只需要看看效果:

只有亮度通道:
1114
只有蓝色色度:
1115
只有红色色度:
1116
在图像视频的加工与储存中,YUV格式一般更受欢迎,理由如下:

1、人眼对亮度的敏感度远高于色度,因此人眼看到的有效信息主要来自于亮度。YUV模型可以将绝大多数的有效信息分配到Y通道。UV通道相对记录的信息少的多。相对于RGB模型较为平均的分配,YUV模型将多数有效信息集中在Y通道,不但减少了冗余信息量,还为压缩提供了便利

2、保持了对黑白显示设备的向下兼容

3、图像编辑中,调节亮度和颜色饱和度,在YUV模型下更方便。

几乎所有的视频格式,以及广泛使用的JPEG图像格式,都是基于YCbCr模型的。播放的时候,播放器需要将YCbCr的信息,通过计算,转换为RGB。这个步骤称为渲染(Rendering)

每个通道的记录,通常是用整数来表示。比如RGB24,就是RGB各8个bit,用0~255 (8bit的二进制数范围)来表示某个颜色的强弱。YUV模型也不例外,也是用整数来表示每个通道的高低。

4、色深

色深(bit-depth),就是我们通常说的8bit和10bit,是指每个通道的精度。8bit就是每个通道用一个8bit整数(0~255)代表,10bit就是用10bit整数(0~1023)来显示。16bit则是0~65535

(注意,上文的表述是不严谨的,视频在编码的时候,并非一定能用到0~255的所有范围,而是可能有所保留,只用到一部分,比如16~235。这我们就不详细展开了)

你的显示器是8bit的,代表它能显示RGB每个通道0~255所有强度。但是视频的色深是YUV的色深,播放的时候,YUV需要通过计算转换到RGB。因此,10bit的高精度是间接的,它使得运算过程中精度增加,以让最后的颜色更细腻。

如何理解8bit显示器,播放10bit是有必要的呢:

一个圆的半径是12.33m, 求它的面积,保留两位小数。

半径的精度给定两位小数,结果也要求两位小数,那么圆周率精度需要给多高呢?也只要两位小数么?
取pi=3.14, 面积算出来是477.37平方米
取pi=3.1416,面积算出来是477.61平方米
取pi精度足够高,面积算出来是477.61平方米。所以取pi=3.1416是足够的,但是3.14就不够了。

换言之,即便最终输出的精度要求较低,也不意味着参与运算的数字,以及运算过程,可以保持较低的精度。在最终输出是8bit RGB的前提下,10bit YUV比起8bit YUV依旧具有精度优势的原因就在这里。事实上,8bit YUV转换后,覆盖的精度大概相当于8bit RGB的26%,而10bit转换后的精度大约可以覆盖97%——你想让你家8bit显示器发挥97%的细腻度么?看10bit吧。

8bit精度不足,主要表现在亮度较低的区域,容易形成色带:
logo11.png
注意这图右边那一圈圈跟波浪一样的效果。这就是颜色精度不足的表现。

10bit的优势不只在于显示精度的提高,在提高视频压缩率,减少失真方面,相对8bit也有优势。这方面就不展开了。

5、色度半采样

在YUV模型的应用中,Y和UV的重要性是不等同的。图像视频的实际储存和传输中,通常将Y以全分辨率记录,UV以减半甚至1/4的分辨率记录。这个手段被称为色度半采样(Chroma Sub-Sampling)。色度半采样可以有效减少传输带宽,和加大UV平面的压缩率,但是不可避免的会损失UV平面的有效信息。

我们平常的视频,最常见的是420采样。配合YUV格式,常常被写作yuv420。这种采样是Y保留全部,UV只以(1/2) x (1/2)的分辨率记录。比如说1920×1080的视频,其实只有亮度平面是1920×1080。两个色度平面都只有960×540的分辨率。

当然了,你也可以选择不做缩减。这种称为444采样,或者yuv444。YUV三个平面全是满分辨率。

在做YUV->RGB的时候,首先需要将缩水的UV分辨率拉升到Y的分辨率(madVR中允许自定义算法,在Chroma Upscaling当中),然后再转换到RGB。做RGB->YUV的转换,也是先转换到444(YUV的分辨率相同),再将UV分辨率降低。

一般能拿到的片源,包括所有蓝光原盘,都是420采样的。所以成品一般也保留420采样。所以yuv420就表示这个视频是420采样的yuv格式。

将420做成444格式,需要自己手动将UV分辨率拉升2×2倍。在今天madVR等渲染器可以很好地拉升UV平面的情况下,这种做法无异于毫无必要的拉升DVD做成伪高清。

当然了,有时候也需要在444/RGB平面下做处理和修复,常见的比如视频本身RGB平面不重叠(比如摩卡少女樱),这种修复过程首先要将UV分辨率拉升,然后转RGB,做完修复再转回YUV。修复后的结果相当于全新构图,这种情况下保留444格式就是有理由,有必要的。

H264格式编码444格式,需要High 4:4:4 Predictive Profile(简称Hi444pp)。所以看到Hi444pp/yuv444 之类的标示,你就需要去找压制者的陈述,为什么他要做这么个拉升。如果找不到有效的理由,你应该默认作者是在瞎做。

6、空间上的低频与高频:平面,纹理和线条

在视频处理中,空间(spatial)的概念指的是一帧图片以内(你可以认为就是一张图所呈现的二维空间/平面)。跟时间(temporal)相对;时间的概念就强调帧与帧之间的变换。

于是我们重新来看这张亮度的图:
1117

亮度变化较快,变动幅度大的区域,我们称之为高频区域。否则,亮度变化缓慢且不明显的区域,我们称为低频区域。

图中的蓝圈就是一块典型的低频区域,或者就叫做平面(平坦的部分)。亮度几乎没有变化

绿圈中,亮度呈现跳跃式的突变,这种高频区域我们称之为线条。

红圈中,亮度频繁变化,幅度有高有低,这种高频区域我们称为纹理。

有时候,线条和纹理(高频区域)统称为线条,平面(低频区域)又叫做非线条。

这是亮度平面。色度平面,高频低频,线条等概念也同样适用,就是描述色度变化的快慢轻重。一般我们所谓的“细节”,就是指图像中的高频信息。

一般来说,一张图的高频信息越多,意味着这张图信息量越大,所需要记录的数据量就越多,编码所需要的运算量也越大。如果一个视频包含的空间性高频信息很多(通俗点说就是每一帧内细节很多),意味着这个视频的空间复杂度很高。

记录一张图片,编码器需要决定给怎样的部分多少码率。码率在一张图内不同部分的分配,叫做码率的空间分配。分配较好的时候,往往整幅图目视观感比较统一;分配不好常见的后果,就是线条纹理尚可,背景平面区域出现大量色带色块(码率被过分的分配给线条);或者背景颜色过渡自然,纹理模糊,线条烂掉(码率被过分的分配给非线条)。

7、时间上的低频与高频:动态

在视频处理中,时间(temporal)的概念强调帧与帧之间的变换。跟空间(spatial)相对。

动态的概念无需多解释;就是帧与帧之间图像变化的强弱,变化频率的高低。一段视频如果动态很高,变化剧烈,我们称为时间复杂度较高,时域上的高频信息多。否则如果视频本身舒缓多静态,我们称为时间复杂度低,时域上的低频信息多。

一般来说,一段视频的时域高频信息多,动态的信息量就大,所需要记录的数据量就越多,编码所需要的运算量也越大。但是另一方面,人眼对高速变化的场景,敏感度不如静态的图片来的高(你没有时间去仔细观察细节),所以动态场景的优先度可以低于静态场景。如何权衡以上两点去分配码率,被称为码率的时间分配。分配较好的时候,看视频无论动态还是静态效果都较好;分配不好的时候往往是静态部分看着还行,动态部分糊烂掉;或者动态部分效果过分的好,浪费了大量码率,造成静态部分欠码,瑕疵明显。

很多人喜欢看静止的截图对比,来判断视频的画质。从观看的角度,这种做法其实并不完全科学——如果你觉得比较烂的一帧其实是取自高动态场景,那么这一帧稍微烂点无可厚非,反正观看的时候你注意不到,将码率省下来给静态部分会更好。

8、清晰度与画质简述

我们经常讨论,一个视频清晰度如何,画质好不好。但是如何给这两个术语做定义呢?

经常看到的说法:“这个视频清晰度是1080p的”。其实看过上文你就应该知道,1080p只是视频的分辨率,它不能直接代表清晰度——比如说,我可以把一个480p的dvd视频拉升到1080p,那又怎样呢?它的清晰度难道就提高了么?

一个比较接近清晰度的概念,是上文所讲述的,空间高频信息量,就是一帧内的细节。一张图,一个视频的细节多,它的清晰度就高。分辨率决定了高频信息量的上限;就是它最清晰能到什么地步。1080p之所以比480p好,是因为它可以允许图像记录的高频信息多。这个说法看样子很靠谱,但是,有反例:
oversharped.png
右图的高频信息远比左图多——它的线条很锐利,有大量致密的噪点(注意噪点完全符合高频信息的定义;它使得图像变化的非常快)
但是你真的觉得右图清晰度高么?
事实上,右图完全是通过左图加工而来。通过过度锐化+强噪点,人为的增加无效的高频信息。

所以清晰度的定义我更倾向于这样一个说法:图像或视频中,原生、有效的高频信息。
原生,强调这种清晰度是非人工添加的;有效;强调细节本身有意义,而不是毫无意义的噪点特效。

值得一提的是,人为增加的高频信息不见得完全没有帮助。有的时候适度锐化的确能够起到不错的目视效果:
finesharped.png

这是一幅适度锐化后的效果。如果有人觉得右图更好,至少某些部分更好,相信我,你不是一个人。所以适度锐化依旧是视频和图像处理中,可以接受的一种主观调整的手段,一定的场合下,它确实有助于提高目视效果。

以上是清晰度的概述。注意,清晰度只是空间方面(就是一帧以内)。如果再考虑到动态效果的优秀与否(视频是不是那种一动起来就糊成一团的,或者动起来感觉卡顿明显的,常见于早起RMVB),空间和时间上优秀的观看效果共同定义了画质。所以我们说madVR/svp那些倍帧效果有助于提高画质,实际上它们增强了时间上的观看效果。

好的画质,是制作者和观众共同追求的。怎么样的视频会有好的画质呢?是不是码率越高的视频画质越好呢?真不见得。视频的画质,是由以下几点共同决定的:

1、源的画质。
俗话说的好,上梁不正下梁歪。如果源的画质本身很差,那么再如何折腾都别指望画质好到哪去。所以压制者往往会选择更好的源进行压制——举个栗子,BDRip一般都比TVRip来的好,哪怕是720p。蓝光也分销售地区,一般日本销售的日版,画质上比美版、台版、港版啥的都来得好,所以同样是BDRip,选取更好的源,就能做到画质上优先一步。

2、播放条件。
观众是否用了足矣支持高画质播放的硬件和软件。这就是为啥我们在发布Rip的同时大力普及好的播放器;有时候一个好的播放器胜过多少在制作方面的精力投入。

3、码率投入vs编码复杂度。
视频的时间和空间复杂度,并称为编码复杂度。编码复杂度高的视频,往往细节多,动态高(比如《魔法少女小圆剧场版 叛逆的物语》),这样的视频天生需要较高的码率去维持一个优秀的观看效果。
相反,有些视频编码复杂度低(比如《请问今天要来点兔子么》,动态少,线条细节柔和),这种视频就是比较节省码率的。

4、码率分配的效率和合理度。
同样多的码率,能起到怎样好的效果,被称为效率。比如H264就比之前的RealVideo效率高;10bit比8bit效率高;编码器先进,参数设置的比较合理,编码器各种高端参数全开(通常以编码时间作为代价),码率效率就高。
合理度就是码率在时空分配方面合理与否,合理的分配,给观众的观看效果就比较统一协调。 码率分配的效率和合理度,是对制作者的要求,要求制作者对片源分析,参数设置有比较到位的理解。

码率分配和合理度做的好,就常常能做出低码率高画质的良心作品。

这里再多提一句,至少在这个时间点,也就是此文发布的2014年年底,HEVC相对于AVC可以提高50%的效率,依旧是一个纸面上的理论值。实际操作中,因为HEVC编码器的成熟度远不及经过了十几年发展的AVC编码器,导致现在HEVC的潜力远没有能发挥出来,特别是高画质下甚至不如。
对于目前主流的,定位收藏画质的BDRip,同样码率下x265的画质相对于x264没有优势;所以在近期,大家不用优先的去下载HEVC版作为收藏目的,更不必迷信什么“码率降低一半”。再强调一次,这个时间点;如果一年后以上陈述被不断进步的HEVC编码器推翻,我毫不惊讶。

5、编码前的预处理。预处理分三种:

①,客观修复。强调修复片源固有的瑕疵,比如锯齿,色带,晕轮等等。
②,主观调整,强调将片源调整的更适合人眼观看,比如适度的锐化,调色(有时候你是可以通过科学方法判定片源的颜色有问题,然后针对的做修复的)。
③,移除无效高频信息,比如降噪,避免码率浪费在无效的噪点上

预处理做的好,往往能达到画质上超越片源,或是在几乎不牺牲清晰度的前提下,节省码率开销。

但是预处理是一把双刃剑,优化的同时,可能引入副效果。降噪、抗锯齿、去晕轮等操作会不可避免的损失一些有效细节(或多或少,取决于制作者水准);主观调整很可能会引入副效果(比如过度锐化会导致锯齿和晕轮),或是变成了作者的自我满足,形成对观众的欺骗。

综上,一个优秀的画质,是由片源、制作者、观看者共同决定的;码率高低也只是部分因素,并非决定性的效果。

于是这篇教程就写到这里吧。它最初的目的是给学习视频制作入门的人而写,也不知道对于一般的观众,能让大家理解多少。有啥需要交流讨论提问的就在下文回复吧。如果反响较好,以后我们还会发布更多这样科普教学类的文章。

chrome的console功能

发表于 2018-02-06 | 分类于 前端

chrome的console功能

Console的9种用法,
1 显示信息的命令

1
2
3
4
console.log('hello');
console.info('信息');
console.error('错误');
console.warn('警告');

2 占位符(格式输出)
console上述的集中度支持printf的占位符格式,支持的占位符有:字符(%s)、整数(%d或%i)、浮点数(%f)和对象(%o)

1
console.log("%d年%d月%d日",2018,2,2);

3 信息分组(嵌套)

group是嵌套,groupEnd是结束一层嵌套

1
2
3
4
5
6
7
8
console.group("第一组信息");        
console.log("第一组第一条");
console.log("第一组第二条");
console.groupEnd();
console.group("第二组信息");
console.log("第二组第一条");
console.log("第二组第二条");
console.groupEnd();

4 查看对象信息

console.dir(obj)可以显示一个对象所有的属性和方法。

1
2
3
4
5
6
var obj = {
name: 'Bob',
age: 30,
message: "hello world"
};
console.dir(obj);

5 显示某个节点的内容

console.dirxml(id)用来显示网页的某个节点(node)所包含的html/xml代码。

6 判断变量是否是真
console.assert(expression, object[, object…])

接收至少两个参数,第一个参数的值或返回值为false的时候,将会在控制台上输出后续参数的值。例如:
用来判断一个表达式或变量是否为真。如果结果为否,则在控制台输出一条相应信息,并且抛出一个异常。

1
2
console.assert(1 == 1, object); // 无输出,返回 undefined
console.assert(1 == 2, object); // 输出 object

7 追踪函数的调用轨迹
console.trace()用来追踪函数的调用过程。在大型项目尤其是框架开发中,函数的调用轨迹可以十分复杂,console.trace()方法可以将函数的被调用过程清楚地输出到控制台上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function tracer(a) {
console.trace();
return a;
}

function foo(a) {
return bar(a);
}

function bar(a) {
return tracer(a);
}

var a = foo('tracer');

8 计时功能
计时器,可以将成对的console.time()和console.timeEnd()之间代码的运行时间输出到控制台上,name参数可作为标签名。

1
2
3
4
5
console.time('计时器');
for (var i = 0; i < 1000; i++) {
for (var j = 0; j < 1000; j++) {}
}
console.timeEnd('计时器');

9 console.profile()的性能分析
性能分析(Profiler)就是分析程序各个部分的运行时间,找出瓶颈所在,使用的方法是console.profile()

这是个挺高大上的东西,可用于性能分析。在 JS 开发中,我们常常要评估段代码或是某个函数的性能。在函数中手动打印时间固然可以,但显得不够灵活而且有误差。借助控制台以及console.profile()方法我们可以很方便地监控运行性能。

例如下面这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
function parent() {
for (var i = 0; i < 10000; i++) {
childA()
}
}

function childA(j) {
for (var i = 0; i < j; i++) {}
}

console.profile('性能分析');
parent();
console.profileEnd();

10 输出执行到该行的次数

console.count([label])

输出执行到该行的次数,可选参数 label 可以输出在次数之前,例如:

1
2
3
4
5
6
7
8
9
10
(function() {
for (var i = 0; i < 5; i++) {
console.count('count');
}
})();
// count: 1
// count: 2
// count: 3
// count: 4
// count: 5

11 可将传入的对象或数组以表格形式输出
console.table()

可将传入的对象,或数组以表格形式输出,相比传统树形输出,这种输出方案更适合内部元素排列整齐的对象或数组,不然可能会出现很多的 undefined。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var obj = {
foo: {
name: 'foo',
age: '33'
},
bar: {
name: 'bar',
age: '45'
}
};

var arr = [
['foo', '33'],
['bar', '45']
];

console.table(obj);
console.table(arr);

你真的了解 console 吗

1…11121314
Henry x

Henry x

this is description

133 日志
25 分类
135 标签
GitHub E-Mail
Links
  • weibo
© 2019 Henry x