Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- [Descaling](encoding/descaling.md)
- [Resampling](encoding/resampling.md)
- [Codecs](encoding/video-encoding.md)
- [x264](encoding/codecs/x264.md)


## Typesetting
Expand Down
309 changes: 309 additions & 0 deletions encoding/codecs/x264.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
# Encoding with x264

H.264 has been the de facto standard video format
across the internet for the past decade.
It is widely supported for playback in all modern browsers
and many hardware devices such as gaming consoles and phones.
It provides better video quality at smaller file sizes
compared to its predecessors.

x264 is a mature, free, open-source encoder
for the H.264 video format.


## Prerequisites

To get started, you'll need two things:

- A video to encode—for the examples,
we will pipe in a video from VapourSynth,
which you should be able to do
if you've been following the previous sections of this guide
- The x264 encoder

Here's how we get a copy of the x264 encoder:


### Windows

Official Windows builds are available
[here](https://download.videolan.org/pub/x264/binaries/win64/).


### Linux/macOS

Generally, x264 will be available
through your distribution's package manager.
Here are a few examples:

- **Ubuntu/Debian**: `sudo apt install x264`
- **Arch Linux**: `sudo pacman -S x264`
- **macOS**: `brew install x264`


## Getting Started

x264 is very configurable,
and the options may seem overwhelming.
But you can get started encoding
by using the presets x264 provides
and understanding a few basic concepts.
We'll walk through those concepts
with the following examples.


### Example 1: General-Purpose Encoding

Open up a terminal window,
and navigate to the folder
where your VapourSynth script lives.
Let's run the following command:

```
vspipe --y4m myvideo.vpy - | x264 --demuxer y4m --preset veryfast --tune animation --crf 24 -o x264output.mkv -
```

Let's run through what each of these options means:


##### `vspipe --y4m myvideo.vpy -`

This portion loads your VapourSynth script
and pipes it to stdout,
adding y4m headers that x264 can decode.
If you use Linux,
you're probably familiar with how piping works.
If you're not,
it's basically a way of chaining two commands together.
In this case, we want to chain `vspipe`,
the program that reads VapourSynth scripts,
with `x264`, our encoder.


##### `--demuxer y4m`

This tells x264 that we're providing it with a y4m file.
This matches up with the `--y4m` flag
that we gave to the `vspipe` command.


##### `--preset veryfast`

x264 has a set of presets
to switch between faster encoding, or higher quality.
The full list of presets, from fastest to slowest, is:

1. ultrafast
1. superfast
1. veryfast
1. faster
1. fast
1. medium
1. slow
1. slower
1. veryslow
1. placebo
Comment on lines +94 to +105
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This numbering is actually okay because it wraps this in an <ol> HTML tag, so the numbers here don't matter.

Copy link
Contributor Author

@shssoichiro shssoichiro Oct 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is the standard way of doing ordered lists in markdown. It makes it easier to add/remove items in the future (though that probably won't happen in this case).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should probably update this on the contributing page, since this is much easier and cleaner looking 👍 .

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I didn't check whether we mention this already, but I use this style in a couple other documentation projects. (Just like semantic line feeds, and I think everyone should use those!)


You will almost never want to use the extreme settings,
but generally, if you want good quality
and don't care about how long the encode takes,
`slower` or `veryslow` are recommended.
In this example,
because we are just demonstrating how x264 works,
we want a fast encode and have chosen `veryfast`.

For the curious,
you can see a full list of the settings enabled by each preset
by running `x264 --fullhelp | less` (Linux/Mac)
or `x264 --fullhelp | more` (Windows).
However, this probably won't mean much at the moment.
Don't worry,
this page will explain later
what all of those settings mean.

*Disclaimer:
x264's `fullhelp` is not guaranteed to be up-to-date.*


##### `--tune animation`

Beyond the preset chosen,
x264 allows us to further tune the encoding settings
for the type of content we're working with.
The following tunings are generally the most useful:

- `film`: Recommended for live action videos.
- `animation`: Recommended for anime or cartoons with flat textures.
For 3D animation (e.g. Pixar movies),
you may find better results with `film`.
- `grain`: Recommended for particularly grainy films.

You don't need to use a tuning,
but it generally helps
to produce a better-looking video.


##### `--crf 24`

CRF is a constant-quality, 1-pass encoding mode.
In layman's terms,
this means that we don't need the output to meet a specific filesize,
we just want the output to meet a certain quality level.
CRF ranges from 0 to 51 (for 8-bit encoding),
with 0 being the best quality
and 51 being the smallest filesize,
but there is a certain range of CRF settings
that are generally most useful.
Here are some guidelines:

- CRF 13: This is considered visually lossless to videophiles.
This can produce rather large files,
but is a good choice if you want high quality videos.
Some fansubbing groups use this for Blu-ray encodes.
- CRF 16-18: This is considered visually lossless to most viewers,
and leans toward high quality
while still providing a reasonable filesize.
This is a typical range for fansub encodes.
- CRF 21-24: This provides a good balance between quality and filesize.
Some quality loss becomes visible,
but this is generally a good choice
where filesize becomes a concern,
such as for videos viewed over the internet.
- CRF 26-30: This prioritizes filesize,
and quality loss becomes more obvious.
It is generally not recommended to go higher than CRF 30
in any real-world encoding scenario,
unless you want your videos to look like they were made for dial-up.


##### `-o x264output.mkv -`

This last portion tells which files to use for the input and output.
We use `-o` to tell which filename to write the encoded file to.
In this case, x264 will write a file at `x264output.mkv`
in the current directory.

The last argument we are passing to x264 is the input file.
In this case, we pass `-` for the input file,
which tells x264 to use the piped output from vspipe.
The input argument is the only positional argument,
so it does not need to be last;
x264 will recognize it
as the only argument without a `--` flag before it.


### Example 2: Targeted File Size

For the next example,
let's say we want to make sure our encode
fits onto a single 4.7GB DVD.
How would we do that in x264?

First, we'll need to figure out
what bitrate our encode should be,
in **kilobits per second**.
This means we'll need to know a couple of things:

- The length of our video, in seconds.
For this example,
let's say our movie is 2 hours (120 minutes) long.
We'll convert that to seconds:
120 minutes \* 60 minutes/second = **7200 seconds**.
- Our target filesize.
We know that this is 4.7GB,
but we need to convert it to kilobits.
We can do this with the following steps:

```
4.7GiB * 1024MiB/GiB = 4812.8MiB
4812.8MiB * 1024KiB/MiB = 4928307.2KiB
4928307.2KiB * 8Kbits/KiB = 39426457.6Kbits
```

Now we divide the kilobit size we calculated by our video length,
to find our kilobit per second target bitrate:

```
39426457.6Kbits / 7200 seconds = 5475 Kbps
```
Comment on lines +217 to +228
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have the option of changing this math to render with TeX (which also might come in handy on other pages where math has been put in codeblocks or in-line currently) with the katex gitbook plug-in. Here's what the changes would look like (and the rendering works with the current text/theme options we give the user).

Currently:

image

With katex:

image
image

I know @FichteFoll has mentioned concerns about adding more plug-ins to the book, so I'll ask for their feedback on this.


With the current 12 plug-ins, initial generation: finished with success in 2.0s
"" on file-changed restart: finished with success in 1.7s

With katex, initial generation: finished with success in 2.5s
"" on file-changed restart: finished with success in 1.9s

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love LateX. Let's do this! Thanks for taking the time to look into (as I considered suggesting this as well but due to being relatively short on time I didn't want to commit to it).


And here's how we could add that to our x264 command:

```
vspipe --y4m myvideo.vpy - | x264 --demuxer y4m --preset veryfast --bitrate 5475 -o x264output.mkv -
```

The `--bitrate` option, by itself,
says that we want to do a 1-pass, average-bitrate encode.
In other words, the encoder will still give more bits
to sections of the video that have more detail or motion,
but the average bitrate of the video
will be close to what we requested.


### Example 3: 2-Pass Encoding

So far, we've only done 1-pass encodes.
While using CRF 1-pass is great
when you don't have a target bitrate,
it's recommended not to use 1-pass
for targeted-bitrate encodes,
because the encoder can't know
what's coming ahead of the current section of video.
This means it can't make good decisions
about what parts of the video need the most bitrate.

How do we fix this?
x264 supports what is known as 2-pass encoding.
In 2-pass mode, x264 runs through the video twice,
the first time analyzing it
to determine where to place keyframes
and which sections of video need the most bitrate,
and the second time performing the actual encode.
2-pass mode is highly recommended
if you need to target a certain bitrate.

Here's how we would run our first pass:

```
vspipe --y4m myvideo.vpy - | x264 --demuxer y4m --preset veryfast --pass 1 --bitrate 5475 -o x264output.mkv -
```

This creates a stats file in our current directory,
which x264 will use in the second pass:

```
vspipe --y4m myvideo.vpy - | x264 --demuxer y4m --preset veryfast --pass 2 --bitrate 5475 -o x264output.mkv -
```

You'll notice all we had to change was `--pass 1` to `--pass 2`. Simple!

Although x264 will automatically use faster settings for the first pass,
it should be no surprise
that 2-pass encoding is slower than 1-pass encoding.
Therefore, there are still certain use cases
where 1-pass, bitrate-targeted video
is a good fit, such as streaming.


## Recap

We covered the basics of how to encode in x264,
including speed presets, tunings, and three different encoding modes.

Here is a summary of when to use each encoding mode:

- 1-pass Constant Quality (CRF):
- Good for: General-purpose encoding
- Bad for: Streaming; obtaining a certain file size
- 1-pass Average Bitrate:
- Good for: Streaming
- Bad for: Everything else
- 2-pass Average Bitrate:
- Good for: Obtaining a certain file size
- Bad for: Streaming


## Advanced Configuration

Coming Soon