Merge pull request #7397 from wxy/master

PRF&PUB:20171004 How To Create A Video From PDF Files In Linux.md
This commit is contained in:
Xingyu.Wang 2018-01-25 20:11:37 +08:00 committed by GitHub
commit 57da5bdbff
2 changed files with 201 additions and 20 deletions

View File

@ -1,70 +1,79 @@
如何在 Linux 中从 PDF 创建视频
======
![](https://www.ostechnix.com/wp-content/uploads/2017/10/Video-1-720x340.jpg)
我在我的平板电脑中收集了大量的 PDF 文件,其中主要是 Linux 教程。有时候我懒得在平板电脑上看。我认为如果我能够从 PDF 创建视频,并在大屏幕设备(如电视机或计算机)中观看会更好。虽然我对 [**FFMpeg**][1] 有一些经验,但我不知道如何使用它来创建视频。经过一番 Google 搜索,我想出了一个很好的解决方案。对于那些想从一组 PDF 文件制作视频文件的人,请继续阅读。这并不困难。
我在我的平板电脑中收集了大量的 PDF 文件,其中主要是 Linux 教程。有时候我懒得在平板电脑上看。我认为如果我能够从 PDF 创建视频,并在大屏幕设备(如电视机或计算机)中观看会更好。虽然我对 [FFMpeg][1] 有一些经验,但我不知道如何使用它来创建视频。经过一番 Google 搜索,我想出了一个很好的解决方案。对于那些想从一组 PDF 文件制作视频文件的人,请继续阅读。这并不困难。
### 在 Linux 中从 PDF 创建视频
为此,你需要在系统中安装 **“FFMpeg”****“ImageMagick”**
为此,你需要在系统中安装 “FFMpeg” 和 “ImageMagick”。
要安装 FFMpeg请参考以下链接。
- [在 Linux 上安装 FFMpeg][2]
Imagemagick 可在大多数 Linux 发行版的官方仓库中找到。
**Arch Linux** 以及 **Antergos** 、**Manjaro Linux** 等衍生产品上,运行以下命令进行安装。
在 Arch Linux 以及 Antergos、Manjaro Linux 等衍生产品上,运行以下命令进行安装。
```
sudo pacman -S imagemagick
```
**Debian、Ubuntu、Linux Mint**
Debian、Ubuntu、Linux Mint
```
sudo apt-get install imagemagick
```
**Fedora**
Fedora
```
sudo dnf install imagemagick
```
**RHEL、CentOS、Scientific Linux**
RHEL、CentOS、Scientific Linux
```
sudo yum install imagemagick
```
**SUSE、 openSUSE**
SUSE、 openSUSE
```
sudo zypper install imagemagick
```
在安装 ffmpeg 和 imagemagick 之后,将你的 PDF 文件转换成图像格式,如 PNG 或 JPG如下所示。
```
convert -density 400 input.pdf picture.png
```
这里,**-density 400** 指定输出图像的水平分辨率。
这里,`-density 400` 指定输出图像的水平分辨率。
上面的命令会将指定 PDF 的所有页面转换为 PNG 格式。PDF 中的每个页面都将被转换成 PNG 文件,并保存在当前目录中,文件名为: **picture-1.png****picture-2.png** 等。根据选择的 PDF 的页数,这将需要一些时间。
上面的命令会将指定 PDF 的所有页面转换为 PNG 格式。PDF 中的每个页面都将被转换成 PNG 文件,并保存在当前目录中,文件名为: `picture-1.png``picture-2.png` 等。根据选择的 PDF 的页数,这将需要一些时间。
将 PDF 中的所有页面转换为 PNG 格式后,运行以下命令以从 PNG 创建视频文件。
```
ffmpeg -r 1/10 -i picture-%01d.png -c:v libx264 -r 30 -pix_fmt yuv420p video.mp4
```
这里:
* **-r 1/10** :每张图像显示 10 秒。
* **-i picture-%01d.png** :读取以 **“picture-”** 开头接着是一位数字01d最后以 **.png** 结尾的所有图片。如果图片名称带有2位数字也就是 picture-10.png、picture11.png 等在上面的命令中使用02d
* **-c:v libx264**:输出的视频编码器(即 h264
* **-r 30** :输出视频的帧率
* **-pix_fmt yuv420p**:输出的视频分辨率
* **video.mp4**:以 .mp4 格式输出视频文件。
* `-r 1/10` :每张图像显示 10 秒。
* `-i picture-%01d.png` :读取以 `picture-` 开头,接着是一位数字(`01d`),最后以 `.png` 结尾的所有图片。如果图片名称带有 2 位数字(也就是 `picture-10.png`、`picture11.png` 等),在上面的命令中使用(`02d`)。
* `-c:v libx264`:输出的视频编码器(即 h264
* `-r 30` :输出视频的帧率
* `-pix_fmt yuv420p`:输出的视频分辨率
* `video.mp4`:以 .mp4 格式输出视频文件。
好了,视频文件完成了!你可以在任何支持 .mp4 格式的设备上播放它。接下来,我需要找到一种方法来为我的视频插入一个很酷的音乐。我希望这也不难。
如果你想要更高的分辨率,你不必重新开始。只要将输出的视频文件转换为你选择的任何其他更高/更低的分辨率,比如说 720p如下所示。
```
ffmpeg -i video.mp4 -vf scale=-1:720 video_720p.mp4
```
@ -73,17 +82,16 @@ ffmpeg -i video.mp4 -vf scale=-1:720 video_720p.mp4
就是这些了。希望你觉得这个有帮助。还会有更好的东西。敬请关注!
--------------------------------------------------------------------------------
via: https://www.ostechnix.com/create-video-pdf-files-linux/
作者:[SK][a]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.ostechnix.com/author/sk/
[1]:https://www.ostechnix.com/20-ffmpeg-commands-beginners/
[2]:https://www.ostechnix.com/install-ffmpeg-linux/

View File

@ -0,0 +1,173 @@
#Translating by qhwdw [Tail Calls, Optimization, and ES6][1]
In this penultimate post about the stack, we take a quick look at tail calls, compiler optimizations, and the proper tail calls landing in the newest version of JavaScript.
A tail call happens when a function F makes a function call as its final action. At that point F will do absolutely no more work: it passes the ball to whatever function is being called and vanishes from the game. This is notable because it opens up the possibility of tail call optimization: instead of [creating a new stack frame][6] for the function call, we can simply reuse F's stack frame, thereby saving stack space and avoiding the work involved in setting up a new frame. Here are some examples in C and their results compiled with [mild optimization][7]:
Simple Tail Calls[download][2]
```
int add5(int a)
{
return a + 5;
}
int add10(int a)
{
int b = add5(a); // not tail
return add5(b); // tail
}
int add5AndTriple(int a){
int b = add5(a); // not tail
return 3 * add5(a); // not tail, doing work after the call
}
int finicky(int a){
if (a > 10){
return add5AndTriple(a); // tail
}
if (a > 5){
int b = add5(a); // not tail
return finicky(b); // tail
}
return add10(a); // tail
}
```
You can normally spot tail call optimization (hereafter, TCO) in compiler output by seeing a [jump][8] instruction where a [call][9] would have been expected. At runtime TCO leads to a reduced call stack.
A common misconception is that tail calls are necessarily [recursive][10]. That's not the case: a tail call may be recursive, such as in finicky() above, but it need not be. As long as caller F is completely done at the call site, we've got ourselves a tail call. Whether it can be optimized is a different question whose answer depends on your programming environment.
"Yes, it can, always!" is the best answer we can hope for, which is famously the case for Scheme, as discussed in [SICP][11] (by the way, if when you program you don't feel like "a Sorcerer conjuring the spirits of the computer with your spells," I urge you to read that book). It's also the case for [Lua][12]. And most importantly, it is the case for the next version of JavaScript, ES6, whose spec does a good job defining [tail position][13] and clarifying the few conditions required for optimization, such as [strict mode][14]. When a language guarantees TCO, it supports proper tail calls.
Now some of us can't kick that C habit, heart bleed and all, and the answer there is a more complicated "sometimes" that takes us into compiler optimization territory. We've seen the [simple examples][15] above; now let's resurrect our factorial from [last post][16]:
Recursive Factorial[download][3]
```
#include <stdio.h>
int factorial(int n)
{
int previous = 0xdeadbeef;
if (n == 0 || n == 1) {
return 1;
}
previous = factorial(n-1);
return n * previous;
}
int main(int argc)
{
int answer = factorial(5);
printf("%d\n", answer);
}
```
So, is line 11 a tail call? It's not, because of the multiplication by n afterwards. But if you're not used to optimizations, gcc's [result][17] with [O2 optimization][18] might shock you: not only it transforms factorial into a [recursion-free loop][19], but the factorial(5) call is eliminated entirely and replaced by a [compile-time constant][20] of 120 (5! == 120). This is why debugging optimized code can be hard sometimes. On the plus side, if you call this function it will use a single stack frame regardless of n's initial value. Compiler algorithms are pretty fun, and if you're interested I suggest you check out [Building an Optimizing Compiler][21] and [ACDI][22].
However, what happened here was not tail call optimization, since there was no tail call to begin with. gcc outsmarted us by analyzing what the function does and optimizing away the needless recursion. The task was made easier by the simple, deterministic nature of the operations being done. By adding a dash of chaos (e.g., getpid()) we can throw gcc off:
Recursive PID Factorial[download][4]
```
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int pidFactorial(int n)
{
if (1 == n) {
return getpid(); // tail
}
return n * pidFactorial(n-1) * getpid(); // not tail
}
int main(int argc)
{
int answer = pidFactorial(5);
printf("%d\n", answer);
}
```
Optimize that, unix fairies! So now we have a regular [recursive call][23] and this function allocates O(n) stack frames to do its work. Heroically, gcc still does [TCO for getpid][24] in the recursion base case. If we now wished to make this function tail recursive, we'd need a slight change:
tailPidFactorial.c[download][5]
```
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int tailPidFactorial(int n, int acc)
{
if (1 == n) {
return acc * getpid(); // not tail
}
acc = (acc * getpid() * n);
return tailPidFactorial(n-1, acc); // tail
}
int main(int argc)
{
int answer = tailPidFactorial(5, 1);
printf("%d\n", answer);
}
```
The accumulation of the result is now [a loop][25] and we've achieved true TCO. But before you go out partying, what can we say about the general case in C? Sadly, while good C compilers do TCO in a number of cases, there are many situations where they cannot do it. For example, as we saw in our [function epilogues][26], the caller is responsible for cleaning up the stack after a function call using the standard C calling convention. So if function F takes two arguments, it can only make TCO calls to functions taking two or fewer arguments. This is one among many restrictions. Mark Probst wrote an excellent thesis discussing [Proper Tail Recursion in C][27] where he discusses these issues along with C stack behavior. He also does [insanely cool juggling][28].
"Sometimes" is a rocky foundation for any relationship, so you can't rely on TCO in C. It's a discrete optimization that may or may not take place, rather than a language feature like proper tail calls, though in practice the compiler will optimize the vast majority of cases. But if you must have it, say for transpiling Scheme into C, you will [suffer][29].
Since JavaScript is now the most popular transpilation target, proper tail calls become even more important there. So kudos to ES6 for delivering it along with many other significant improvements. It's like Christmas for JS programmers.
This concludes our brief tour of tail calls and compiler optimization. Thanks for reading and see you next time.
--------------------------------------------------------------------------------
via:https://manybutfinite.com/post/tail-calls-optimization-es6/
作者:[Gustavo Duarte][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:http://duartes.org/gustavo/blog/about/
[1]:https://manybutfinite.com/post/tail-calls-optimization-es6/
[2]:https://manybutfinite.com/code/x86-stack/tail.c
[3]:https://manybutfinite.com/code/x86-stack/factorial.c
[4]:https://manybutfinite.com/code/x86-stack/pidFactorial.c
[5]:https://manybutfinite.com/code/x86-stack/tailPidFactorial.c
[6]:https://manybutfinite.com/post/journey-to-the-stack
[7]:https://github.com/gduarte/blog/blob/master/code/x86-stack/asm-tco.sh
[8]:https://github.com/gduarte/blog/blob/master/code/x86-stack/tail-tco.s#L27
[9]:https://github.com/gduarte/blog/blob/master/code/x86-stack/tail.s#L37-L39
[10]:https://manybutfinite.com/post/recursion/
[11]:http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html
[12]:http://www.lua.org/pil/6.3.html
[13]:https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tail-position-calls
[14]:https://people.mozilla.org/~jorendorff/es6-draft.html#sec-strict-mode-code
[15]:https://github.com/gduarte/blog/blob/master/code/x86-stack/tail.c
[16]:https://manybutfinite.com/post/recursion/
[17]:https://github.com/gduarte/blog/blob/master/code/x86-stack/factorial-o2.s
[18]:https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
[19]:https://github.com/gduarte/blog/blob/master/code/x86-stack/factorial-o2.s#L16-L19
[20]:https://github.com/gduarte/blog/blob/master/code/x86-stack/factorial-o2.s#L38
[21]:http://www.amazon.com/Building-Optimizing-Compiler-Bob-Morgan-ebook/dp/B008COCE9G/
[22]:http://www.amazon.com/Advanced-Compiler-Design-Implementation-Muchnick-ebook/dp/B003VM7GGK/
[23]:https://github.com/gduarte/blog/blob/master/code/x86-stack/pidFactorial-o2.s#L20
[24]:https://github.com/gduarte/blog/blob/master/code/x86-stack/pidFactorial-o2.s#L43
[25]:https://github.com/gduarte/blog/blob/master/code/x86-stack/tailPidFactorial-o2.s#L22-L27
[26]:https://manybutfinite.com/post/epilogues-canaries-buffer-overflows/
[27]:http://www.complang.tuwien.ac.at/schani/diplarb.ps
[28]:http://www.complang.tuwien.ac.at/schani/jugglevids/index.html
[29]:http://en.wikipedia.org/wiki/Tail_call#Through_trampolining