分类 Ubuntu 下的文章

“Ubuntu是以桌面应用为主的Linux发行版,基于Debian。Ubuntu有三个正式版本,包括桌面版、服务器版及用于物联网设备和机器人的Core版。从17.10版本开始,Ubuntu以GNOME为默认桌面环境。 Ubuntu是著名的Linux发行版之一,也是目前最多用户的Linux版本。 ”

cURL百科
cURL是一个开源项目,主要的产品是curl(命令行工具)和libcurl(C语言的API库),两者功能均是:基于网络协议,对指定URL进行网络传输。

cURL涉及是任何网络协议传输,不涉及对具体数据的具体处理。curl支持的通信协议有DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SBMS, SMTP, SMTPS, TELNET 和TFTP。

cURL 官方网站

https://curl.se/

cURL 例子
cURL 简单模式:

$ curl http://example.com

cURL 详细(verbose)模式:

$ curl --verbose http://example.com
$ curl -v http://example.com

cURL 下载(output):

$ curl --output output.html http://example.com/
$ curl -o output.html http://example.com/

cURL 重定向:(curl默认不会重定向)

$ curl --location output.html http://example.com/
$ curl -L output.html http://example.com/

使用 curl 在命令行获取网站的响应时间

curl -L -w "time_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_pretransfer: %{time_pretransfer}\ntime_redirect: %{time_redirect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" https://example.com/

结果:

<!doctype html>
<html>
...
</html>
time_namelookup: 0.020519
time_connect: 0.187338
time_appconnect: 0.546461
time_pretransfer: 0.546661
time_redirect: 0.000000
time_starttransfer: 0.710620
time_total: 0.710879

time_appconnect and time_connect time tells us how much time is spent in SSL/TLS handshake. For a cleartext connection without SSL/TLS, this number is reported as zero.
Also note that time_redirect is zero in both outputs above. That is because no redirection occurs while visiting example.com.

curl post file as body
curl POST 二进制文件
strip new lines

curl --data "@/path/to/filename" http://...

keep new lines

curl --data-binary "@/path/to/filename" http://...

zmq介绍
ØMQ (也拼写作ZeroMQ,0MQ或ZMQ)是一个为可伸缩的分布式或并发应用程序设计的高性能异步消息库。它提供一个消息队列, 但是与面向消息的中间件不同,ZeroMQ的运行不需要专门的消息代理(message broker)。该库设计成常见的套接字风格的API。

ZeroMQ是由iMatix公司和大量贡献者组成的社群共同开发的。 ZMQ 是一个简单好用的传输层,像框架一样的一个socket library,他使得Socket编程更加简单、简洁和性能更高。是一个消息处理队列库,可在多个线程、内核和主机盒之间弹性伸缩。ZMQ 的明确目标是“成为标准网络协议栈的一部分,之后进入 Linux 内核。

libzmq 下载地址

https://github.com/zeromq/libzmq/archive/refs/tags/v4.3.4.tar.gz

zmq github地址

https://github.com/zeromq/libzmq/

cppzmq github地址

https://github.com/zeromq/cppzmq

cppzmq 下载地址

https://github.com/zeromq/cppzmq/archive/refs/tags/v4.8.1.tar.gz

cppzmq 介绍

cppzmq is a C++ binding for libzmq. It has the following design goals:

cppzmq maps the libzmq C API to C++ concepts. In particular:
it is type-safe (the libzmq C API exposes various class-like concepts as void*)
it provides exception-based error handling (the libzmq C API provides errno-based error handling)
it provides RAII-style classes that automate resource management (the libzmq C API requires the user to take care to free resources explicitly)
cppzmq is a light-weight, header-only binding. You only need to include the header file zmq.hpp (and maybe zmq_addon.hpp) to use it.
zmq.hpp is meant to contain direct mappings of the abstractions provided by the libzmq C API, while zmq_addon.hpp provides additional higher-level abstractions.

ubuntu 下编译 libzmq

wget https://github.com/zeromq/libzmq/archive/refs/tags/v4.3.4.tar.gz
tar xvf v4.3.4.tar.gz
cd libzmq-4.3.4/
./autogen.sh
mkdir build && cd build
cmake ..
make

cmake的时候提示没有libsodium,安装就好。

sudo apt install libsodium-dev

指定安装路径

cmake -DCMAKE_INSTALL_PREFIX=$(pwd)/../../install.x64 ..

make install 即可。

ubuntu 下编译cppzmq

wget https://github.com/zeromq/cppzmq/archive/refs/tags/v4.8.1.tar.gz
tar xvf v4.8.1.tar.gz
cd cppzmq-4.8.1/
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=$(pwd)/../../install.x64 ..
make install

Zmq通信场景

  • 线程之间(inproc)
  • 进程之间(ipc)
  • 机器之间(tcp)

Zmq通信模式

  • 请求-回复(Request-reply)。分为ZMQ_REQ、ZMQ_REP、ZMQ_DEALER、ZMQ_ROUTER
    REQ-REP模式是阻塞式的,也就是说必须要client先发送一条消息给server,然后server才可以返回一个response给client。任何顺序上的错误都会导致报错。

a) 服务端和客户端无论谁先启动,效果是相同的,这点不同于Socket。

b) 在服务端收到信息以前,程序是阻塞的,会一直等待客户端连接上来。

c) 服务端收到信息以后,会send一个“World”给客户端。值得注意的是一定是client连接上来以后,send消息给Server,然后Server再rev然后响应client,这种一问一答式的。如果Server先send,client先rev是会报错的。

d) ZMQ通信通信单元是消息,他除了知道Bytes的大小,他并不关心的消息格式。因此,你可以使用任何你觉得好用的数据格式。Xml、Protocol Buffers、Thrift、json等等。

  • 发布-订阅(Publish-subscribe)。分为ZMQ_PUB、ZMQ_SUB
    发布者只是绑定了端口,并进行信息发布,其并不care是否有接收者,有哪些接收者。

要说明的两点就是:

  1. 服务器端一直不断的广播中,如果中途有 Subscriber 端退出,并不影响他继续的广播,当 Subscriber 再连接上来的时候,收到的就是后来发送的新的信息了。这对比较晚加入的,或者是中途离开的订阅者,必然会丢失掉一部分信息,这是这个模式的一个问题,所谓的 Slow joiner。

注意这个slow joiner问题,之后会为了解决这个问题而设计新的模式。

2.但是,如果 Publisher 中途离开,所有的 Subscriber 会 hold 住,等待 Publisher 再上线的时候,会继续接受信息。

  • 管道(Pipeline)。分为ZMQ_PUSH、ZMQ_PULL
    管道模式(Pipeline) 这样的场景,如果需要统计各个机器的日志,我们需要将统计任务分发到各个节点机器上,最后收集统计结果,做一个汇总。PipeLine 比较适合于这种场景。Pipeline的原理就是:有一个Publisher来发布任务,这些任务是可以平行执行的。有一批Worker用于接收任务,Worker处理完任务之后就将结果发送到Sink之中用于归总或进一步处理。

所以要明确的是Pipeline之中并不是服务器,客户端的关系了,而是有三种对象——Ventilator,Worker,Sink
task ventilator 使用的是bind SOCKET_PUSH,将任务分发到 Worker 节点上。而 Worker 节点上,使用 connect SOCKET_PULL 从上游接受任务,并使用connect SOCKET_PUSH 将结果汇集到bind Slink。

  • 对立对(Exclusive pair)。分为ZMQ_PAIR

libzmq 交叉编译

./configure --host=arm-linux-gnueabihf --without-libsodium --prefix=$(pwd)/../install.arm --disable-libbsd

zmq_proxy_steerable 说明

int zmq_proxy_steerable (const void *frontend, const void *backend, const void *capture, const void *control);

第四个参数“control”。如果控制socket不为NULL,这个代理支持后续的控制操作。如果这个socket接收到SUSPEND0消息,此代理将延迟它的活动。如果接到了RESUME0消息,它将继续工作。如果收到了TERMINATE0消息,它将平滑的(smoothly)结束。如果接到了STATISTICS0消息 代理将回复控制套接字,发送一个8帧的多部分消息,每个消息具有64位的无符号整数,其顺序如下:前端套接字接收的消息数===>前端套接字接收的字节数===>发送给前端套接字的消息数量===>前端套接字发送的字节数===>后端套接字接收的消息数===>后端套接字接收的字节数===>发送后端套接字的消息数===>发送后端套接字的字节数。
如果控制socket为NULL,此函数和zmq_proxy的工作方式一样。
当控制socket接收到TERMINATE时zmq_proxy_steerable()函数返回0,。否则,返回 -1,并且设置errno为ETERM。
创建一个共享的代理队列

//  Create frontend, backend and control sockets
void *frontend = zmq_socket (context, ZMQ_ROUTER);
assert (backend);
void *backend = zmq_socket (context, ZMQ_DEALER);
assert (frontend);
void *control = zmq_socket (context, ZMQ_SUB);
assert (control);
//  Bind sockets to TCP ports
assert (zmq_bind (frontend, "tcp://*:5555") == 0);
assert (zmq_bind (backend, "tcp://*:5556") == 0);
assert (zmq_connect (control, "tcp://*:5557") == 0);
// Subscribe to the control socket since we have chosen SUB here
assert (zmq_setsockopt (control, ZMQ_SUBSCRIBE, "", 0));
//  Start the queue proxy, which runs until ETERM or "TERMINATE" received on the control socket zmq_proxy (frontend, backend, NULL, control);

在另一个节点上创建一个控制器,进程或者其它

void *control = zmq_socket (context, ZMQ_PUB);
assert (control);
assert (zmq_bind (control, "tcp://*:5557") == 0);
// stop the proxy 
assert (zmq_send (control, "STOP", 5, 0) == 0);
// resume the proxy
assert (zmq_send (control, "RESUME", 7, 0) == 0);
// terminate the proxy
assert (zmq_send (control, "TERMINATE", 10, 0) == 0);

zmq router dealer 介绍

“请求-响应”代理使用ZMQ_ROUTER、ZMQ_DEALER
ZMQ_DEALER
ZMQ_DEALER类型的套接字是用于扩展“请求/应答”套接字的高级模式
发送消息时:当ZMQ_DEALER套接字由于已达到所有对等点的最高水位而进入静音状态时,或者如果根本没有任何对等点,则套接字上的任何zmq_send()操作都应阻塞,直到静音状态结束或至少一个对等方变得可以发送;消息不会被丢弃
接收消息时:发送的每条消息都是在所有连接的对等方之间进行轮询,并且收到的每条消息都是从所有连接的对等方进行公平排队的
将ZMQ_DEALER套接字连接到ZMQ_REP套接字时,发送的每个消息都必须包含一个空的消息部分,定界符以及一个或多个主体部分
REQ和ROUTER交流,DEALER与REP交流。

我们的代理必须是非阻塞的,可以使用zmq_poll()来轮询任何一个套接字上的活动,但我们不能使用REQ-REQ。幸运地是,有两个称为DEALER和ROUTER的套接字,它们能我们可以执行无阻塞的请求-响应

客户端的流程如下:将REQ套接字连接到代理的ROUTER节点上,向ROUTER节点发送“Hello”,接收到“World”的回复
服务端的流程如下:将REP套接字连接到代理的DEALER节点上
代理端的流程如下:
创建一个ROUTER套接字与客户端相连接,创建一个DEALER套接字与服务端相连接
ROUTER套接字从客户端接收请求数据,并把请求数据发送给服务端
DEALER套接字从服务端接收响应数据,并把响应数据发送给客户端
客户端的消息是有顺序到达客户端的,消息会自动进行排队

ZMQ_ROUTER 兼容的对等套接字 ZMQ_DEALER、ZMQ_REQ、ZMQ_ROUTER
ZMQ_DEALER 兼容的对等套接字 ZMQ_ROUTER、ZMQ_REP、ZMQ_DEALER

“请求-响应模型”支持的套接字类型有4种:
ZMQ_REP
ZMQ_REQ
ZMQ_DEALER
ZMQ_ROUTER

php zmq

安装 sudo apt install php-zm

php zmq 示例

<?php

/* Create new queue object */
$queue = new ZMQSocket(new ZMQContext(), ZMQ::SOCKET_PUB);
$queue->connect("tcp://127.0.0.1:5554");

while (1) {
  $queue->send("hello there!");
}

php zmq req示例

<?php

/* Create new queue object */
$queue = new ZMQSocket(new ZMQContext(), ZMQ::SOCKET_REQ, "MySock1");

/* Connect to an endpoint */
$queue->connect("tcp://127.0.0.1:5555");

/* send and receive */
var_dump($queue->send("hello there, using socket 1")->recv());

?>

php zmq req 非阻塞示例

<?php

/* Create new queue object */
$queue = new ZMQSocket(new ZMQContext(), ZMQ::SOCKET_REQ, "MySock1");
$queue->connect("tcp://127.0.0.1:5555");

/* Assign socket 1 to the queue, send and receive */
$retries = 5;
$sending = true;
$sent    = false;

$queue->setSockOpt (ZMQ::SOCKOPT_LINGER, 1000);

echo "Trying to send message\n";
do {
    try {
        if ($sending) {
            if ($queue->send("This is a message", ZMQ::MODE_DONTWAIT) !== false) {
                echo "Message sent\n";
                $sent    = true;
                $sending = false;
            }
        }
    } catch (ZMQSocketException $e) {
        die(" - Error: " . $e->getMessage());
    }
    usleep (1000);
} while (1 && --$retries);

$retries = 2;
$receiving = true;
$received  = false;

echo "Trying to receive message\n";
do {
    try {
        if ($receiving) {
            $message = $queue->recv (ZMQ::MODE_DONTWAIT);
            
            if ($message) {
                echo "Received message: " . $message . "\n";
                $receiving = false;
                $received = true;
            }
        }
    } catch (ZMQSocketException $e) {
        die(" - Error: " . $e->getMessage());
    }
    sleep (1);
} while (1 && --$retries);

if (!$received) {
    echo "The receive timed out\n";
}

?>

更多php-zmq示例
https://github.com/zeromq/php-zmq/tree/master/examples

ZeroMQ设置超时等待

设置一下超时等待,避免阻塞。

使用方法:

int timeout = 1000;
zmq_setsockopt (requester, ZMQ_RCVTIMEO, &timeout, sizeof(timeout));
zmq_setsockopt (requester, ZMQ_SNDTIMEO, &timeout, sizeof(timeout));

php zmq pipe line 示例
https://www.cnblogs.com/jkko123/p/6294575.html
pipeline中,send.php通过把累加任务分发给50个worker节点计算,然后worker节点计算完成后,把结果发送给result.php进行统一的汇总。

sender:

$sed = new ZMQSocket($context, ZMQ::SOCKET_PUSH);
$sed->bind("tcp://127.0.0.1:8881");

worker:

$rev = new ZMQSocket($context, ZMQ::SOCKET_PULL);
$rev->connect("tcp://127.0.0.1:8881"); 
$sed = new ZMQSocket($context, ZMQ::SOCKET_PUSH);
$sed->connect("tcp://127.0.0.1:8882");

result:

$rev = new ZMQSocket($context, ZMQ::SOCKET_PULL); 
$rev->bind("tcp://127.0.0.1:8882");

C/C++使用ZeroMQ的Router/Dealer模式搭建高性能后台服务框架
ROUTER/DEALER的优点
没错,就是简单使用ZeroMQ提供的ROUTER/DEALER组合模式,可以轻松搭建一个高性能异步的C/C++后台服务框架。ROUTER可 以高效的接收客户端的请求,而DEALER可以负载均衡的调度后端Worker工作。当客户端的请求特别多,后端Worker处理不过来,需要增加 Worker的时候,也非常简单,新加入的Worker直接Connect到DEALER即可。如此运维起来也非常高效,后端可以非常简单的横向扩展!值的一提的是,ROUTER又叫做XREP,DEALER又叫做XREQ。

Dealer将后端Worker的应答数据转发到Router。
然后由Router寻址将应答数据准确的传递给对应的client。
值得注意的是,Router对client的寻址方式,得看client的‘身份’。
临时身份的client,Router会为其生成一个uuid进行标识。
永久身份的client,Router直接使用该client的身份。
ZMQ_REP套接字,其实就是一个“应答”,即,把应答数据回复给ZMQ_REQ,他们是严格的一问一答的方式。不过组合上 ZMQ_ROUTER,ZMQ_DEALER模式后,后台Worker不再是服务的死穴,可以通过横向扩展多个Worker来提高处理ZMQ_REQ的能 力。

ZMQ_REQ是“问”的套接字,它需要“答”套接字(ZMQ_REP)。不过目前ZMQ_REP已经被 ROUTER/DEALER华丽的包装成高富帅了。ZMQ_REQ只能通过联系ROUTER,然后由这个ROUTER/DEALER组成的DEVICE帮 忙传递“爱意”到达ZMQ_REP了,然后再默默的期待ROUTER传递ZMQ_REQ的“答复”。

ZeroMQ的ROUTER/DEALER模式

1、客户端(ZMQ_REQ)发送请求到ROUTER后,ROUTER是会对客户端进行身份表示的,正式因为有这个身份标示,所以ROUTER才有能力正确的把应答数据准确的传递到来源的客户端。

现在可以回答一下上文的一个思考题了—-ROUTER传递的3帧数据到底是什么数据:

A、第一帧是ROUTER自己加上的消息,这个是ROUTER对ZMQ_REQ所做的一个身份标识。说到身份标识,这里就引入到两种套接字。

一种叫做临时套接字,另外一种叫做永久套接字,他们的区别仅仅是是否使用ZMQ_IDENTITY。

没使用的即默认为临时套接字,我的这个文章里面的例子就是一个临时套接字。对于临时套接字,ROUTER会为它生成一个唯一的UUID,所以可以看到第一帧的长度为5,正是这个UUID。

而使用如下方式设定的套接字,则称为永久套接字。如果这样设置,那第一帧收到的消息长度就是13,而ROUTER也会直接使用www.example.com这个身份来标识这个客户端。

zmq_setsockopt(req, ZMQ_IDENTITY, “www.example.com”, 13);

B、第二帧是一个空帧,这是由REQ加上去的。可以理解为一个分隔符,当ROUTER遇到这个空帧后,就知道下一帧就是真正的请求数据了,这在多种组合模型里面尤其有用。

C、第三帧显然就是真正的请求数据了。这里的例子比较简单,复杂的例子,客户端可能会通过ZMQ_SNDMORE来发送多帧数据。如果是这样,那ROUTER还会继续收到第四帧,第五帧。。。数据的。

2、REQ到达ROUTER,ROUTER会公平排队,并公平的将REQ发往后端。但当后端能力不足的时候,导致ROUTER派发太慢的时候,ROUTER进入高水位的时候,ROUTER会丢弃掉消息的。所以这个得注意监控后台服务的性能。

3、DEALER会负载均衡的将任务派发后连接到它的各个工作Worker。
https://hottaro.com/index.php?document_srl=256&mid=Framework

ffmpeg 维基百科
FFmpeg 是一个开放源代码的自由软件,可以执行音频和视频多种格式的录影、转换、串流功能,包含了libavcodec——这是一个用于多个项目中音频和视频的解码器库,以及libavformat——一个音频与视频格式转换库。

“FFmpeg”这个单词中的“FF”指的是“Fast Forward(快速前进)”。有些新手写信给“FFmpeg”的项目负责人,询问FF是不是代表“Fast Free”或者“Fast Fourier”等意思,“FFmpeg”的项目负责人回信说:“Just for the record, the original meaning of "FF" in FFmpeg is "Fast Forward"...”

这个项目最初是由法国程序员法布里斯·贝拉(Fabrice Bellard)发起的,而现在是由迈克尔·尼德梅尔(Michael Niedermayer)在进行维护。许多FFmpeg的开发者同时也是MPlayer项目的成员,FFmpeg在MPlayer项目中是被设计为服务器版本进行开发。

2011年3月13日,FFmpeg部分开发人士决定另组Libav,同时制定了一套关于项目继续发展和维护的规则。

ffmpeg 命令行程序
命令行应用程序
ffmpeg:用于对视频文档或音频档案转换格式
ffplay:一个简单的播放器,基于SDL与FFmpeg库
ffprobe:用于显示媒体文件的信息,见MediaInfo
ffmpeg 常用参数
参数明细可用ffmpeg -h显示;编解码器名称等明细可用ffmpeg -formats显示。

下列为较常使用的参数:

主要参数

-i——设置输入文件名。
-f——设置输出格式。
-y——若输出文件已存在时则覆盖文件。
-fs——超过指定的文件大小时则结束转换。
-t——指定输出文件的持续时间,以秒为单位。
-ss——从指定时间开始转换,以秒为单位。
-ss和-t一起使用时代表从-ss的时间开始转换持续时间为-t的视频,例如:-ss 00:00:01.00 -t 00:00:10.00即从00:00:01.00开始转换到00:00:11.00。
-title——设置标题。
-timestamp——设置时间戳。
-vsync——增减Frame使影音同步。
-c——指定输出文件的编码。
-metadata——更改输出文件的元数据。
-help——查看帮助信息。
影像参数
-b:v——设置影像流量,默认为200Kbit/秒。(单位请引用下方注意事项)
-r——设置帧率值,默认为25。
-s——设置画面的宽与高。
-aspect——设置画面的比例。
-vn——不处理影像,于仅针对声音做处理时使用。
-vcodec( -c:v )——设置影像影像编解码器,未设置时则使用与输入文件相同之编解码器。

ffmpeg linux shell 批量提取音频内容

cat cc.sh 
#!/bin/sh
 
 
folder="."
id=0
for file_a in ${folder}/*
do
    let id++
    in_filename=`basename $file_a`
    num=`echo $id | awk '{printf("%02d",$0)}'`;
    out_filename="output/$num.aac"
    if [ "${in_filename##*.}"x = "mp4"x ]||[ "${in_filename##*.}"x = "ts"x ];then
    ffmpeg -i $in_filename -vn  $out_filename 
    fi
done

ffmpeg 下载 m3u8

ffmpeg -i http://.../playlist.m3u8 -c copy -bsf:a aac_adtstoasc output.mp4

ffmpeg aac_adtstoasc 格式说明

官方说明地址在这儿:https://ffmpeg.org/ffmpeg-bitstream-filters.html#aac_005fadtstoasc
*Convert MPEG-2/4 AAC ADTS to an MPEG-4 Audio Specific Configuration bitstream.
This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4 ADTS header and removes the ADTS header.
This filter is required for example when copying an AAC stream from a raw ADTS AAC or an MPEG-TS container to MP4A-LATM, to an FLV file, or to MOV/MP4 files and related formats such as 3GP or M4A. Please note that it is auto-inserted for MP4A-LATM and MOV/MP4 and related formats.*

1)将AAC编码器编码后的原始码流(ADTS头 + ES流)封装为MP4或者FLV或者MOV等格式时,需要先将ADTS头转换为MPEG-4 AudioSpecficConfig (将音频相关编解码参数提取出来),并将原始码流中的ADTS头去掉(只剩下ES流)。
2)相反,从MP4或者FLV或者MOV等格式文件中解封装出AAC码流(只有ES流)时,需要在解析出的AAC码流前添加ADTS头(含音频相关编解码参数)。

ubuntu ffmpeg screen capture

ffmpeg -f x11grab -video_size 1920x1030 -framerate 50 -i :0.0 -vf format=yuv420p output.mp4

Capturing your Desktop / Screen Recording for Linux
Use the x11grab device:

ffmpeg -video_size 1024x768 -framerate 25 -f x11grab -i :0.0+100,200 output.mp4

This will grab the image from desktop, starting with the upper-left corner at x=100, y=200 with a width and height of 1024⨉768.

If you need audio too, you can use ALSA (see Capture/ALSA for more info):

ffmpeg -video_size 1024x768 -framerate 25 -f x11grab -i :0.0+100,200 -f alsa -ac 2 -i hw:0 output.mkv

Or the pulse input device (see Capture/PulseAudio for more info):

ffmpeg -video_size 1024x768 -framerate 25 -f x11grab -i :0.0+100,200 -f pulse -ac 2 -i default output.mkv

ffmpeg 编译参数

ffmpeg -version

ffmpeg version N-105038-g30322ebe3c Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 9 (Ubuntu 9.3.0-17ubuntu1~20.04)
configuration: --enable-libx264 --enable-libpulse --enable-gpl --enable-openssl --enable-nonfree --enable-x86asm --enable-libmp3lame --enable-libx265 --enable-librtmp

ffmpeg 编解码列表

$ ffmpeg -codecs
$ ffmpeg -encoders
$ ffmpeg -decoders
$ ffmpeg -formats

ffmpeg 错误 OpenSSL <3.0.0 is incompatible with the gpl

Add --enable-nonfree

ffmpeg 录制电脑音频

pactl list short sources

1 alsa_output.pci-0000_00_1f.3.analog-stereo.monitor module-alsa-card.c s16le 2ch 48000Hz IDLE
2 alsa_input.pci-0000_00_1f.3.analog-stereo module-alsa-card.c s16le 2ch 48000Hz SUSPENDED

ffmpeg pulse 电脑录音

ffmpeg -f pulse -i 1 -ac 1 out.mp3

You can reference sources either by number: -f pulse -i 5, or by name -f pulse -i alsa_input.pci-0000_00_1b.0.analog-stereo, or just use -f pulse -i default to use the source currently set as default in pulseaudio.

ffmpeg 麦克风录音

ffmpeg -f pulse -i alsa_input.pci-0000_00_1b.0.analog-stereo -ac 1 recording.m4a

ffmpeg 录取播放声音

ffmpeg -f pulse -i alsa_output.pci-0000_00_1b.0.analog-stereo.monitor -ac 2 recording.m4a

Linux 录取电脑音视频

ffmpeg -video_size 1024x768 -framerate 25 -f x11grab -i :0.0+100,200 -f pulse -ac 2 -i 1 output.mkv

move the moov atom to the begining of the video file using FFMpeg

ffmpeg -i input_video_file.mp4 -vcodec copy -acodec copy -movflags faststart output_video_file.mp4

ffmpeg 分割mp4

ffmpeg -i input.mp4 -c copy -segment_time 30 -f segment output%03d.mp4

ffmpeg -i input.mp4 -c copy -segment_time 30 -f segment -segment_start_number 1 -individual_header_trailer 1 -break_non_keyframes 1 -reset_timestamps 1 output%03d.mp4

FFMPEG推流到rtsp server 命令
FFmpeg推流
注意:在推流之前先运行rtsp-simple-server,下载地址: https://github.com/bluenviron/mediamtx/releases

UDP推流

ffmpeg -re -i input.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/stream

TCP推流

ffmpeg -re -i input.mp4 -c copy -rtsp_transport tcp -f rtsp rtsp://127.0.0.1:8554/stream

循环推流

ffmpeg -re -stream_loop -1 -i input.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/stream

其中:

-re 为以流的方式读取;

-stream_loop 为循环读取视频源的次数,-1为无限循环;

-i 为输入的文件;

-f 为格式化输出到哪里;
Referenced from:https://blog.csdn.net/chan1987818/article/details/128219230

ffmpeg 生成白底视频

ffmpeg -f lavfi -i color=White:1280x720:d=360 -format rgb32 -f matroska  test1.mp4

ls -lh test1.mp4 
-rw-rw-r-- 1 hesy hesy 412K  5月  7 10:05 test1.mp4
ffmpeg -i test1.mp4 
Input #0, matroska,webm, from 'test1.mp4':
  Metadata:
    ENCODER         : Lavf58.76.100
  Duration: 00:06:00.00, start: 0.000000, bitrate: 9 kb/s
  Stream #0:0: Video: h264 (High), yuv420p(progressive), 1280x720 [SAR 1:1 DAR 16:9], 25 fps, 25 tbr, 1k tbn, 50 tbc (default)

ffmpeg -i test1.mp4 -vcodec libx264 -preset ultrafast -b:v 2000k  output1.mp4

ffmpeg -i output1.mp4 -vf "subtitles=output.srt:force_style='FontName=Arial,FontSize=18,PrimaryColour=&H00FF00&,Outline=2,Shadow=1,BackColour=&H000000&,Bold=-1,Alignment=2,MarginV=135'" output2.mp4

ffmpeg 单张图片生成视频

ffmpeg -loop 1 -i 1.png -s 1280x720 -t 100 output.mp4

-loop 1 :因为只有一张图片所以必须加入这个参数(循环这张图片)
-t :图片转换成视频的持续时长,单位是秒(S),必须指定该值,否则会无限制生成视频
-s :指定视频的分辨率

ffmpeg转场特效:

ffmpeg -i 1.mp4 -vf fade=in:0:5 out.mp4   前5帧淡入
ffmpeg -i 1.mp4 -vf fade=out:35:40 out.mp4   后5帧淡出
ffmpeg -i 1.mp4 -vf fade=in:0:3,fade=out:37:40 out.mp4   前3帧淡入 后3帧淡出

ffmpeg 视频四宫格

ffmpeg -i 1.mp4 -i 2.mp4 -i  3.mp4 -i  4.mp4 -filter_complex "nullsrc=size=640x480[base];[0:v] setpts=PTS-STARTPTS,scale=320x240[upperleft];[1:v]setpts=PTS-STARTPTS,scale=320x240[upperright];[2:v]setpts=PTS-STARTPTS, scale=320x240[lowerleft];[3:v]setpts=PTS-STARTPTS,scale=320x240[lowerright];[base][upperleft]overlay=shortest=1[tmp1];[tmp1][upperright]overlay=shortest=1:x=320[tmp2];[tmp2][lowerleft]overlay=shortest=1:y=240[tmp3];[tmp3][lowerright]overlay=shortest=1:x=320:y=240" out.mp4

 1.2.3.4.mp4为文件路径

ffmpeg 视频实现各种特效
直接上命令:

//渐入
ffmpeg -i in.mp4 -vf fade=in:0:90 out.mp4
//黑白
ffmpeg -i in.mp4 -vf lutyuv="u=128:v=128" out.mp4
//锐化
ffmpeg -i in.mp4 -vf unsharp=luma_msize_x=7:luma_msize_y=7:luma_amount=2.5 out.mp4
//反锐化
ffmpeg -i in.mp4 -vf unsharp=7:7:-2:7:7:-2 out.mp4
//渐晕
ffmpeg -i in.mp4 -vf vignette=PI/4 out.mp4
//闪烁渐晕
ffmpeg -i in.mp4 -vf vignette='PI/4+random(1)*PI/50':eval=frame out.mp4
//视频颤抖
ffmpeg -i in.mp4 -vf crop="in_w/2:in_h/2:(in_w-out_w)/2+((in_w-out_w)/2)sin(n/10):(in_h-out_h)/2+((in_h-out_h)/2)sin(n/7)" out.mp4
//色彩变幻
ffmpeg -i in.mp4 -vf hue="H=2PIt:s=sin(2PIt)+1" out.mp4
//模糊处理
ffmpeg -i in.mp4 -vf boxblur=5:1:cr=0:ar=0 out.mp4
//镜像翻转
ffmpeg -i in.mp4 -vf crop=iw/2:ih:0:0,splitleft;[tmp]hflip[right];[left]pad=iw*2[a];aoverlay=w out.mp4
//水平翻转
ffmpeg -i in.mp4 -vf geq=p(W-X\,Y) out.mp4
//垂直翻转
ffmpeg -i in.mp4 -vf vflip out.mp4
//浮雕效果
ffmpeg -i in.mp4 -vf format=gray,geq=lum_expr='(p(X,Y)+(256-p(X-4,Y-4)))/2' out.mp4
//均匀噪声
ffmpeg -i in.mp4 -vf noise=alls=20:allf=t+u out.mp4

来源:https://www.cnblogs.com/famhuai/p/ffmpeg.html

视频中去水印delogo
ffmpeg -i input.mp4 -vf delogo=x=0:y=0:w=100:h=60 output.mp4
语法:-vf delogo=x:y:w:h[:t[:show]]
x:y 离左上角的坐标
w:h logo的宽和高
show:默认值0,若设置为1,指定区域的边界会绘制一个绿色的矩形框用于找到合适的x、y、w、h参数。

Use the enable option
The delogo filter supports the enable option (timeline support). You can see if a filter supports this option with ffmpeg -filters.

Apply delogo filter between 5-10 seconds

ffmpeg -i input.mp4 -vf "delogo=x=1539:y=23:w=353:h=93:enable='between(t,5,10)'" -c:a copy output.mp4

Apply delogo to multiple areas

ffmpeg -i input.mp4 -vf "delogo=x=1539:y=23:w=353:h=93,delogo=x=100:y=24:w=100:h=72" -c:a copy output.mp4

Apply delogo to two squares between 5-10 seconds

ffmpeg -i input.mp4 -vf "delogo=x=1539:y=23:w=353:h=93:enable='between(t,5,10)',delogo=x=100:y=24:w=100:h=72:enable='between(t,5,10)'" -c:a copy output.mp4

ffmpeg -i yun.mp4 -t 10 -vf "delogo=x=20:y=30:w=175:h=55:show=1,delogo=x=1020:y=30:w=210:h=60:show=1" output.mp4

多个区域消除logo

ffmpeg -i output.mp4 -vf "delogo=x=200:y=600:w=800:h=100:show=0:enable='between(n,0,50)',delogo=x=20:y=15:w=300:h=80:show=0:enable='between(t,11,26)',delogo=x=20:y=15:w=300:h=80:show=0:enable='between(t,54,68)',delogo=x=20:y=15:w=300:h=80:show=0:enable='between(t,94,108)',delogo=x=20:y=15:w=300:h=80:show=0:enable='between(t,130,142)',delogo=x=20:y=15:w=300:h=80:show=0:enable='between(t,165,177)',delogo=x=20:y=15:w=300:h=80:show=0:enable='between(t,201,216)'"  output1.mp4

ffmpeg视频[片头]添加3秒的图片视频

ffmpeg -y -loop 1 -framerate 1 -t 3 -i /storage/emulated/0/1/input.png -i /storage/emulated/0/1/input.mp4 -f lavfi -t 3.0 -i anullsrc=channel_layout=stereo:sample_rate=44100 -filter_complex [0:v]scale=iw:ih[outv0];[1:v]scale=iw:ih[outv1];[outv0][outv1]concat=n=2:v=1:a=0:unsafe=1[outv];[2:a][1:a]concat=n=2:v=0:a=1[outa] -map [outv] -map [outa] -r 15 -b 1M -f mp4 -vcodec libx264 -c:a aac -pix_fmt yuv420p -s 960x540 -preset superfast /storage/emulated/0/1/result.mp4

ffmpeg视频片头添加3秒的图片视频简化已测试验证通过版本,图片和视频分辨率不要求一样,会自动转换

ffmpeg -y -loop 1 -framerate 1 -t 3 -i 2005.png -i output.mp4 -f lavfi -t 3.0 -i anullsrc=channel_layout=stereo:sample_rate=44100 -filter_complex "[0:v][1:v]concat=n=2:v=1:a=0:unsafe=1[outv];[2:a][1:a]concat=n=2:v=0:a=1[outa]" -map [outv] -map [outa] -r 25 -b 1M -f mp4 -vcodec libx264 -c:a aac -pix_fmt yuv420p -s 1280x720 -preset superfast result.mp4

参考: https://cloud.tencent.com/developer/article/1672609

视频[片尾]添加3秒的图片视频

ffmpeg -y -i /storage/emulated/0/1/input.mp4 -loop 1 -framerate 25 -t 3.0 -i /storage/emulated/0/1/input.png -f lavfi -t 3.0 -i anullsrc=channel_layout=stereo:sample_rate=44100 -filter_complex [0:v]scale=iw:ih[outv0];[1:v]scale=iw:ih[outv1];[outv0][outv1]concat=n=2:v=1:a=0:unsafe=1[outv];[0:a][2:a]concat=n=2:v=0:a=1[outa] -map [outv] -map [outa] -r 25 -b 1M -f mp4 -vcodec libx264 -c:a aac -pix_fmt yuv420p -s 960x540 -preset superfast /storage/emulated/0/1/result.mp4

图片合成视频(带动画)

ffmpeg -y -loop 1 -r 25 -i /storage/emulated/0/1/input.png -vf zoompan=z=1.1:x='if(eq(x,0),100,x-1)':s='960*540' -t 10 -pix_fmt yuv420p /storage/emulated/0/1/result.mp4

视频转Gif

ffmpeg -y -ss 0 -t 7 -i /storage/emulated/0/1/input.mp4 -r 5 -s 280x606 -preset superfast /storage/emulated/0/1/result.gif

Gif转视频

ffmpeg -y -i /storage/emulated/0/1/input.gif -pix_fmt yuv420p -preset superfast /storage/emulated/0/1/result.mp4

添加水印

ffmpeg -y -i /storage/emulated/0/1/input.mp4 -i /storage/emulated/0/1/input.png -filter_complex [0:v]scale=iw:ih[outv0];[1:0]scale=0.0:0.0[outv1];outv0overlay=0:0 -preset superfast /storage/emulated/0/1/result.mp4

添加背景音乐(支持调节原音和配乐的音量)

ffmpeg -y -i /storage/emulated/0/1/input.mp4 -i /storage/emulated/0/1/input.mp3 -filter_complex [0:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,volume=0.2[a0];[1:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,volume=1[a1];a0amix=inputs=2:duration=first[aout] -map [aout] -ac 2 -c:v copy -map 0:v:0 -preset superfast /storage/emulated/0/1/result.mp4

截取指定时间的一张图)

ffmpeg -y -i /storage/emulated/0/1/input.mp4 -f image2 -ss 00:00:03 -vframes 1 -preset superfast /storage/emulated/0/1/result.jpg

视频转图片(每隔一秒截取一张图)

ffmpeg -y -i /storage/emulated/0/1/input.mp4 -f image2 -r 1 -q:v 10 -preset superfast /storage/emulated/0/1/%3d.jpg

FFmpeg文档汇总:https://ffmpeg.org/documentation.html

FFmpeg filters文档:https://ffmpeg.org/ffmpeg-filters.html

视频拼接

ffmpeg -y -f concat -safe 0 -i Cam01.txt -c copy Cam01.mp4

音频拼接

ffmpeg -y -i "concat:123.mp3|124.mp3" -acodec copy output.mp3

音频处理
音频拼接
代码语言:javascript
复制
ffmpeg -y -i "concat:123.mp3|124.mp3" -acodec copy output.mp3
-i代表输入参数

contact:123.mp3|124.mp3代表着需要连接到一起的音频文件

-acodec copy output.mp3 重新编码并复制到新文件中

音频混音
代码语言:javascript
复制
ffmpeg -y -i 124.mp3 -i 123.mp3 -filter_complex amix=inputs=2:duration=first:dropout_transition=2 -f mp3 remix.mp3
-i代表输入参数

-filter_complex ffmpeg滤镜功能,非常强大,详细请查看文档

amix是混合多个音频到单个音频输出

inputs=2代表是2个音频文件,如果更多则代表对应数字

duration 确定最终输出文件的长度

longest(最长)|shortest(最短)|first(第一个文件)

dropout_transition The transition time, in seconds, for volume renormalization when an input stream ends. The default value is 2 seconds.

-f mp3 输出文件格式

音频裁剪
ffmpeg -y -i 124.mp3 -vn -acodec copy -ss 00:00:00 -t 00:01:32 output.mp3
-i代表输入参数

-acodec copy output.mp3 重新编码并复制到新文件中

-ss 开始截取的时间点

-t 截取音频时间长度

视频格式转换

ffmpeg -i input.avi c:a copy c:v copy output.mp4
ffmpeg -i input.mp4 output.ts

分离/合并视频音频流

ffmpeg -i input-video -vn -c:a copy output-audio //分离音频流
//-vn is no video.
//-acodec copy says use the same audio stream that's already in there.

ffmpeg -i input-video -c:v copy -an output-video //分离视频流
//-an is no audio.
//-vcodec copy says use the same video stream that's already in there.
ffmpeg -i input-video -c:v copy -an output-video -c:a -vn output-audio //同时分离音频和视频流
ffmpeg -i video_file -i audio_file -c:v copy -c:a copy output_file //合并视频音频

截取视频片段

ffmpeg -ss 5 -i input.mp4 -t 10 -c:v copy -c:a copy output.mp4
//-ss 5指定从输入视频第5秒开始截取,-t 10指明最多截取10秒。
//而-c:v copy -c:a copy标示视频与音频的编码不发生改变,而是直接复制,这样会大大提升速度

截取10s到20s

ffmpeg -i input.mp4 -c:v libx264 -filter:v select="between(t, 10, 20)" out.mp4

从头截取前10帧

ffmpeg -i input.mp4 -c:v libx264 -filter:v select="gt(n, -1)" -vframes 10 out.mp4
ffmpeg -i input.mp4 -c:v libx264 -filter:v select="between(n, 0, 9)" out.mp4

中间截取 (10-20帧)

ffmpeg -i input.mp4 -c:v libx264 -filter:v select="between(n, 10, 20)" out.mp4

视频转换为m3u8格式

ffmpeg -i yoona.mp4 -c copy -map 0 -f segment -segment_list yoona.m3u8 -segment_time 10 yoona-%04d.ts

把视频文件推送到rtmp服务器

ffmpeg -re -i jack.mp4 -c copy -f flv rtmp://host/live/test

对视频进行切片

ffmpeg -i input.mp4 -c copy -f segment -segment_format mp4 -segment_time 300 -reset_timestamps 1 test_output-%d.mp4
以上命令把input.mp4切分为5分钟时长的视频片段。

按照时间点进行剪切

ffmpeg -i input.mp4 -c copy -f segment -segment_format mp4 -segment_times 60,120,150 -reset_timestamps 1 test_output-%d.mp4
在第60秒、第120秒和第150秒这三个时间点进行切片。

视频截图
获取视频时间点01:23:45的截图

ffmpeg -ss 01:23:45 -i input -vframes 1 -q:v 2 output.jpg

-i input file the path to the input file
-ss 01:23:45 seek the position to the specified timestamp
-vframes 1 only handle one video frame
-q:v 2 to control output quality. Full range is a linear scale of 1-31 where a lower value results in a higher quality. 2-5 is a good range to try.
output.jpg output filename, should have a well-known extension

截取视频帧序号34的图像,帧序号从0开始。

ffmpeg -i <input> -vf "select=eq(n,34)" -vframes 1 out.png

视频/图片尺寸修改

ffmpeg -i sample.jpg -s w*h out.jpg

分离视频的YUV通道分量

ffmpeg -i jack.mp4 -filter_complex "extractplanes=y+u+vy[v]" -map "[y]" jack_y.mp4 -map "[u]" jack_u.mp4 -map "[v]" jack_v.mp4

图片序列与视频的互相转换

ffmpeg -i %04d.jpg output.mp4
ffmpeg -i input.mp4 %04d.jpg
\第一行命令是把0001.jpg、0002.jpg、0003.jpg等编码成output.mp4,
\第二行则是相反把input.mp4变成0001.jpg……。
\%04d.jpg表示从1开始用0补全的4位整数为文件名的jpg文件序列。

视频加水印
ffmpeg -i xizong.mp4 -i fleight.jpg -filter_complex "overlay=W-w-5:5" -codec:a copy xizong_fleight.mp4
//在右上角加水印,边距为5像素。

视频旋转transpose
顺时针翻转90度

ffmpeg -i input -vf transpose=1 output
翻转180度

ffmpeg -i in.mp4 -vf "transpose=1,transpose=1" out.mp4

调色3DLutFilter
应用颜色查找表Lut,有‘nearest’、‘trilinear’、‘tetrahedral’三种插值算法,命令行调用如下:

ffmpeg -i log.mp4 -vf lut3d="file=DK79.cube" out.mp4

图像/视频转换成黑白的
图像转换成黑白的

ffmpeg -i sample.png -vf hue=s=0 output.png

//把视频转换为黑白的
ffmpeg -i julin_5s.mp4 -vf hue=s=0 -c:a copy julin_monochrome.mp4

裁剪视频crop
使用-crop选项,语法如下:

crop=ow[:oh[:x[:y[:keep_aspect]]]]
ow、oh表示裁减之后输出视频的宽和高,
x、y表示在输入视频上开始裁减的横坐标和纵坐标,
keep_aspect: 1表示保持裁剪后输出的纵横比与输入一致,0表示不保持。
裁剪输入视频的左三分之一,中间三分之一,右三分之一:
ffmpeg -i input -vf crop=iw/3:ih :0:0 output
ffmpeg -i input -vf crop=iw/3:ih :iw/3:0 output
ffmpeg -i input -vf crop=iw/3:ih :iw/3*2:0 output
裁剪中间一半区域:
ffmpeg -i input -vf crop=iw/2:ih/2 output

视频尺寸缩放scale
将输入的1920x1080缩小到960x540输出

ffmpeg -i input.mp4 -vf scale=960:540 output.mp4
//ps: 如果540不写,写成-1,即scale=960:-1, 那也是可以的,ffmpeg会通知缩放滤镜在输出时保持原始的宽高比。

视频中去水印delogo
ffmpeg -i input.mp4 -vf delogo=x=0:y=0:w=100:h=60 output.mp4
使用delogo filter
它对logo周围像素的简单插值来实现。只需设置一个覆盖logo的矩形。在每个方向上,紧靠矩形外的下一个像素的值将用于计算矩形内的插值像素值。

语法:-vf delogo=x:y:w:h[:t[:show]]
x:y 离左上角的坐标
w:h logo的宽和高
show:默认值0,若设置为1,指定区域的边界会绘制一个绿色的矩形框用于找到合适的x、y、w、h参数。
给视频或图像加上黑边pad
比如一个输入视频尺寸是1280x534的源,想要加上黑边变成1280x720,使用下面的命令可以实现。

ffmpeg -i input.mp4 -vf pad=1280:720:0:93:black output.mp4
按照从左到右的顺序依次为:“宽”、“高”、“X坐标”和“Y坐标”,宽和高指的是输入视频尺寸(包含加黑边的尺寸),X、Y指的是视频所在位置。
默认是加黑色的边,black可以不写。
上面的命令中93是根据(720-534) / 2计算得到。
如果视频原始1920x800的话,完整的语法应该是:

-vf 'scale=1280:534,pad=1280:720:0:93:black'

先将视频缩小到1280x534,然后在加入黑边变成1280x720,将1280x534的视频放置在x=0,y=93的地方。

视频按时间拼接
使用 FFmpeg 的concat 工具。

先创建一个文本文件,包含需要拼接的文件的列表。

filelist.txt:

file 'input1.mp4'
file 'input2.mp4'
file 'input3.mp4'
命令

ffmpeg -f concat -i filelist.txt -c copy output.mp4

视频左右拼接

ffmpeg -ss 00:05:00 -i v1.mp4 -ss -ss 00:05:00 -i v2.mp4 -filter_complex "[0:v]crop=iw/2:ih:0:0[v1];[1:v]crop=iw/2:ih:iw/2:0[v2];v1hstack[v3];[v3]drawbox=iw/2-1:0:2:ih[v4]" -map [v4] -map 0:a -c:a copy -c:v libx264 -t 00:01:00 -y out.mp4

打印视频帧的一些信息showinfo

ffmpeg -hide_banner -i v.mp4 -vf showinfo -frames:v 1 -f null /dev/null

生成纯色的图片
生成黑色的图片

ffmpeg -f lavfi -i color=Black:640x480 -frames:v 1 -y black.jpg

打印帧序号/pts到视频帧水印drawtext
打印帧序号

ffmpeg -i test.mp4 -vf drawtext=fontcolor=red:fontsize=40:fontfile=msyh.ttf:line_spacing=7:text=%{n}:x=50:y=50 -vsync 0 -y out.mp4
打印帧pts

ffmpeg -i test.mp4 -vf drawtext=fontcolor=red:fontsize=30:fontfile=msyh.ttf:line_spacing=7:text=%{pts}:x=50:y=50 -vsync 0 -y out.mp4
打印帧类型

ffmpeg -i test.mp4 -vf drawtext=fontcolor=red:fontsize=20:fontfile=msyh.ttf:line_spacing=7:text=%{pict_type}:x=50:y=50 -vsync 0 -y out.mp4
把视频的pts[时间戳]添加为视频水印,精度到毫秒

ffmpeg -i test.mp4 -vf “drawtext=fontsize=60:text=’%{pts:hms}’” -c:v libx264 -c copy -f mp4 output.mp4 -y

fmpeg或ffplay 打开 DEBUG 日志输出。
$ ffplay -v debug $URL
API中开启debug日志

av_log_set_level(AV_LOG_DEBUG);

FFmpeg命令日志输出到文件
执行ffmpeg或者ffprobe输出重定向到文件的时候发现文件是空的。
可以采用下面的方式。

ffprobe xxx > file 2>&1

参考网址: https://zhuanlan.zhihu.com/p/544522172

FFmpeg给视频添加背景图片

ffmpeg -loop 1 -i 1.jpg -i input.mp4 -filter_complex 'overlay=(W-w)/2:(H-h)/2:shortest=1,format=yuv420p' -c:a copy test.mp4

FFmpeg将1080p视频提速4倍并调整为720p

ffmpeg -r 100 -i 20240506160722.mp4 -r 25 -s 1280x720 -b 1500k -y  4x.mp4

FFmpeg转码为ios能播放的mp4文件

ffmpeg -i result.mp4 -c:v libx264 -pix_fmt yuv420p -profile:v high -level:v 4.1 -c:a copy  output.mp4 

多个视频overlay

ffmpeg -i 2.mp4 -i s.mp4 -filter_complex "[0][1]overlay=0:638[v1];[v1][1]overlay=128:638[v2];[v2][1]overlay=256:638[v3];[v3][1]overlay=384:638[v4];[v4][1]overlay=512:638[v5];[v5][1]overlay=640:638[v6];[v6][1]overlay=768:638[v7];[v7][1]overlay=896:638[v8];[v8][1]overlay=1024:638[v9];[v9][1]overlay=1152:638" output1.mp4
ffmpeg -i output1.mp4 -i s.mp4 -filter_complex "[0][1]overlay=0:638[v1];[v1][1]overlay=128:638[v2];[v2][1]overlay=256:638[v3];[v3][1]overlay=384:638[v4];[v4][1]overlay=512:638[v5];[v5][1]overlay=640:638[v6];[v6][1]overlay=768:638[v7];[v7][1]overlay=896:638[v8];[v8][1]overlay=1024:638[v9];[v9][1]overlay=1152:638" output2.mp4

FFmpeg ALL中文文档,非常详细的介绍
https://www.jishuchi.com/books/ffmpeg-all

画网格的命令
ffmpeg -i ji_ok.mp4 -vf "drawgrid=w=iw/3:h=ih/3:t=5:color=white@0.6" ji_grid.mp4

生成黑色视频
ffmpeg -f lavfi -i color=Black:1280x720:d=211 black.mp4

将前景视频放到黑底视频上面
ffmpeg -i black.mp4 -i j0v.mp4 -fileter_complex "0overlay=x=75:y=0" b_j0v.mp4

将多个前景视频放到黑底视频上面
ffmpeg -i black.mp4 -i j0v.mp4 -i j1v.mp4 -filter_complex "0overlay=x=75:y=0[v1];v1overlay=x=75:y=650" b_ji.mp4

在视频上面画个框
ffmpeg -i ji_ok.mp4 -vf "drawbox=x=80:w=900:h=650:c=white" -t 10 j1.mp4
查看滤镜的帮助文档
ffmpeg -h filter=drawbox

在视频上显示当前播放的帧号
ffmpeg -i ji_ok.mp4 -vf "drawtext=fontfile=Arial.ttf: text='%{frame_num}': start_number=1: x=(w-tw)/2: y=h-(2*lh): fontcolor=black: fontsize=20: box=1: boxcolor=white: boxborderw=5" j1.mp4

下雪的滤镜视频:
root@3cf1c295cf5f:/usr/local/bin# xvfb-run -a --server-args="-screen 0 1280x720x24 -ac -nolisten tcp -dpi 96 +extension RANDR" ffmpeg -i /home/hesy/output.mp4 -filter_complex "plusglshader=sdsource=snow_shader.gl:vxsource=star_vertex.gl" -c:v libx264 -pix_fmt yuv420p -profile:v high -level:v 4.1 -c:a copy result.mp4

抠图
ffmpeg -i 44s.mp4 -stream_loop -1 -i dance.mp4 -filter_complex "[1:v]scale=720x900,colorkey=0x95949a:0.01:1[1v];0:voverlay=1:2" -t 45 out.mp4

Record audio from an application
Load the snd_aloop module:

modprobe snd-aloop pcm_substreams=1
Set the default ALSA audio output to one substream of the Loopback device in your .asoundrc (or /etc/asound.conf)

.asoundrc

pcm.!default { type plug slave.pcm "hw:Loopback,0,0" }
You can now record audio from a running application using:

ffmpeg -f alsa -ac 2 -ar 44100 -i hw:Loopback,1,0 out.wav

解决ffmpeg推流转发频繁丢包问题_ffmpeg丢包

在代码中加入 -rtsp_transport tcp 即可解决,推流好几个小时无报错

ffmpeg -rtsp_transport tcp -i "rtsp://admin:password@192.168.1.1/h264/ch1/sub/av_stream" -c:v libx264 -c:a copy -s 384*288 -rtsp_transport tcp -stimeout 15000000 -max_delay 500000 -f rtsp -r 50 -an "rtsp://www.baidu.com/94fea02d64444399ac4546e5298eec96_kejian"

由于某些软件并没有增加开启启动的服务,很多时候需要手工添加,一般我们都是推荐添加命令到 /etc/rc.local 文件,但是 默认不带 /etc/rc.local 文件,而 rc.local 服务却还是自带的

root@Ubuntu ~ # cat /lib/systemd/system/rc.local.service
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# This unit gets pulled automatically into multi-user.target by
# systemd-rc-local-generator if /etc/rc.local is executable.
[Unit]
Description=/etc/rc.local Compatibility
ConditionFileIsExecutable=/etc/rc.local
After=network.target

[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
RemainAfterExit=yes
GuessMainPID=no

并且默认情况下这个服务还是关闭的状态

root@Ubuntu ~ # systemctl status rc-local
● rc-local.service - /etc/rc.local Compatibility
   Loaded: loaded (/lib/systemd/system/rc-local.service; static; vendor preset: enabled)
  Drop-In: /lib/systemd/system/rc-local.service.d
           └─debian.conf
   Active: inactive (dead)

为了解决这个问题,我们需要手工添加一个 /etc/rc.local 文件

cat <<EOF >/etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

exit 0
EOF

然后赋予权限

chmod +x /etc/rc.local

接着启动 rc-local 服务

systemctl start rc-local

如果出错呢,就在rc-local.service中添加下面内容

[Install]
WantedBy=multi-user.target
Alias=rc-local.service

再次查看状态

root@Ubuntu ~ # systemctl status rc-local
● rc-local.service - /etc/rc.local Compatibility
   Loaded: loaded (/lib/systemd/system/rc-local.service; static; vendor preset: enabled)
  Drop-In: /lib/systemd/system/rc-local.service.d
           └─debian.conf
   Active: active (exited) since Thu 2017-08-03 09:41:18 UTC; 14s ago
  Process: 20901 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS)

Aug 03 09:41:18 xtom-hk systemd[1]: Starting /etc/rc.local Compatibility...
Aug 03 09:41:18 xtom-hk systemd[1]: Started /etc/rc.local Compatibility.
然后你就可以把需要开机启动的命令添加到 /etc/rc.local 文件,丢在 exit 0 前面即可,并尝试重启以后试试是否生效了
Referenced from:https://sb.sb/blog/debian-9-rc-local/

安装aria2

sudo apt install aria2

启动aria2

aria2c --conf-path=/etc/.aria2/aria2c.conf -D

aria2c.conf看这里https://github.com/P3TERX/aria2.conf

aria2 下载示例

aria2c 'magnet:?xt=urn:btih:6e9f28f581fcec156cb3453caf477e4fabf45b5e&dn=%EA%B7%80%EB%A9%B8%EC%9D%98+%EC%B9%BC%EB%82%A0+%EB%82%A8%EB%A7%A4%EC%9D%98+%EC%97%B0%EC%83%81%EC%98%81%EC%A4%91+Demon+Slayer+Kimetsu+no+Yaiba+SIBLINGS+BOND.2021.1080p.KOR.FHDRip.H264.AAC-JTC.mkv&xl=2464537015&tr=udp://tracker.openbittorrent.com:80/announce&tr=udp://tracker.opentrackr.org:1337/announce'

aria2c rpc 下载示例

curl -v -X POST -d '{"jsonrpc": "2.0", "id": "const","method": "aria2.addUri", "params": ["token:P3TERX",["magnet:?xt=urn:btih:6e9f28f581fcec156cb3453caf477e4fabf45b5e&dn=%EA%B7%80%EB%A9%B8%EC%9D%98+%EC%B9%BC%EB%82%A0+%EB%82%A8%EB%A7%A4%EC%9D%98+%EC%97%B0%EC%83%81%EC%98%81%EC%A4%91+Demon+Slayer+Kimetsu+no+Yaiba+SIBLINGS+BOND.2021.1080p.KOR.FHDRip.H264.AAC-JTC.mkv&xl=2464537015&tr=udp://tracker.openbittorrent.com:80/announce&tr=udp://tracker.opentrackr.org:1337/announce"],{"out":"","dir":"/home/pi/down/"}]}' http://localhost:6800/jsonrpc

命令执行结果:

{"id":"const","jsonrpc":"2.0","result":"24cd0ec304ff6820"}

aria2c 继续下载
 当aria2c异常退出时,或者手动退出时,使用相同的命令就可以继续下载了。通过相同的命令重新启动aria,它将正确地恢复下载。前提是有按照aria2c.conf中保存了aria2.session.

aria2c 'magnet:?xt=urn:btih:5813fb39c0bd2e70efbeef2f37ac61a5ec0c80aa&dn=%EC%9C%A0%EC%B2%B4%EC%9D%B4%ED%83%88%EC%9E%90+Spiritwalker%2C2021.1080p.FHDRip.H264.AAC-NonDRM&xl=3374432532&tr=udp://tracker.openbittorrent.com:80/announce&tr=udp://tracker.opentrackr.org:1337/announce'

aria2c rcp 示例
最全的说明,肯定是官方的文档 https://aria2.github.io/manual/en/html/aria2c.html
The following example adds http://example.org/file:

import urllib2, json
jsonreq = json.dumps({'jsonrpc':'2.0', 'id':'qwer',
                      'method':'aria2.addUri',
                      'params':[['http://example.org/file']]})
c = urllib2.urlopen('http://localhost:6800/jsonrpc', jsonreq)
c.read()
'{"id":"qwer","jsonrpc":"2.0","result":"2089b05ecca3d829"}'

使用curl命令行操作

curl -v -d '{"jsonrpc":"2.0", "id":"qwer","method":"aria2.addUri","params":["token:const",["http://example.org/file"]]}' http://localhost:6800/jsonrpc

{"id":"qwer","jsonrpc":"2.0","result":"6d6994d4933bd2af"}

aria2c 删除下载任务aria2.remove
This method removes the download denoted by gid (string). If the specified download is in progress, it is first stopped. The status of the removed download becomes removed. This method returns GID of removed download.

The following examples remove a download with GID#2089b05ecca3d829.

JSON-RPC Example

import urllib2, json
jsonreq = json.dumps({'jsonrpc':'2.0', 'id':'qwer',
                      'method':'aria2.remove',
                      'params':['2089b05ecca3d829']})
c = urllib2.urlopen('http://localhost:6800/jsonrpc', jsonreq)
c.read()
'{"id":"qwer","jsonrpc":"2.0","result":"2089b05ecca3d829"}'

aria2c rpc 常用命令
aria2.addTorrent
aria2.addMetalink
aria2.remove
aria2.forceRemove
aria2.pause
aria2.pauseAll
aria2.forcePause
aria2.forcePauseAll
aria2.unpause
aria2.unpauseAll
aria2.tellStatus
aria2.getUris
This method returns the URIs used in the download denoted by gid (string). The response is an array of structs and it contains following keys. Values are string.
aria2.getFiles
This method returns the file list of the download denoted by gid (string). The response is an array of structs which contain following keys. Values are strings.
aria2.getPeers
This method returns a list peers of the download denoted by gid (string). This method is for BitTorrent only. The response is an array of structs and contains the following keys. Values are strings.
aria2.getServers
This method returns currently connected HTTP(S)/FTP/SFTP servers of the download denoted by gid (string). The response is an array of structs and contains the following keys. Values are strings.
aria2.tellActive
This method returns a list of active downloads. The response is an array of the same structs as returned by the aria2.tellStatus() method. For the keys parameter, please refer to the aria2.tellStatus() method.

aria2.tellWaiting
This method returns a list of waiting downloads, including paused ones. offset is an integer and specifies the offset from the download waiting at the front. num is an integer and specifies the max. number of downloads to be returned. For the keys parameter, please refer to the aria2.tellStatus() method.
aria2.tellStopped
This method returns a list of stopped downloads. offset is an integer and specifies the offset from the least recently stopped download. num is an integer and specifies the max. number of downloads to be returned. For the keys parameter, please refer to the aria2.tellStatus() method.
aria2.changePosition
This method changes the position of the download denoted by gid in the queue. pos is an integer. how is a string. If how is POS_SET, it moves the download to a position relative to the beginning of the queue. If how is POS_CUR, it moves the download to a position relative to the current position. If how is POS_END, it moves the download to a position relative to the end of the queue. If the destination position is less than 0 or beyond the end of the queue, it moves the download to the beginning or the end of the queue respectively. The response is an integer denoting the resulting position.
aria2.changeUri
This method removes the URIs in delUris from and appends the URIs in addUris to download denoted by gid. delUris and addUris are lists of strings. A download can contain multiple files and URIs are attached to each file.
aria2.getOption
This method returns options of the download denoted by gid. The response is a struct where keys are the names of options. The values are strings. Note that this method does not return options which have no default value and have not been set on the command-line, in configuration files or RPC methods.
aria2.changeOption
This method changes options of the download denoted by gid (string) dynamically. options is a struct.
aria2.getGlobalOption
This method returns the global options.
aria2.changeGlobalOption
This method changes global options dynamically.
aria2.getGlobalStat
This method returns global statistics such as the overall download and upload speeds.
curl 命令示例

curl -d '{"jsonrpc":"2.0", "id":"qwer","method":"aria2.getGlobalStat","params":["token:P3TERX"]}' http://localhost:6800/jsonrpc

{"id":"qwer","jsonrpc":"2.0","result":{"downloadSpeed":"0","numActive":"0","numStopped":"5","numStoppedTotal":"5","numWaiting":"0","uploadSpeed":"0"}}

aria2.purgeDownloadResult
This method purges completed/error/removed downloads to free memory.
aria2.removeDownloadResult
This method removes a completed/error/removed download denoted by gid from memory.
aria2.getVersion
This method returns the version of aria2 and the list of enabled features.
aria2.getSessionInfo
This method returns session information.
aria2.shutdown
This method shuts down aria2. This method returns OK.

aria2.forceShutdown
This method shuts down aria2(). This method behaves like :func:'aria2.shutdown` without performing any actions which take time, such as contacting BitTorrent trackers to unregister downloads first. This method returns OK.

aria2.saveSession
This method saves the current session to a file specified by the --save-session option. This method returns OK if it succeeds.

system.multicall
This methods encapsulates multiple method calls in a single request.

system.listMethods()
This method returns all the available RPC methods in an array of string.
system.listNotifications()
This method returns all the available RPC notifications in an array of string.

aria2c xmlrpc 示例
xmlrpc 地址:http://localhost:6800/rpc

aria2c 下载命令汇总

Download a file from two different HTTP servers¶

 aria2c "http://host/file.zip" "http://mirror/file.zip"

Download a file from one host using multiple connections¶

 aria2c -x2 -k1M "http://host/file.zip"

Note

The -x option specified the number of allowed connections, while the -k option specified the size of chunks.

Download a file from HTTP and FTP servers at the same time¶

 aria2c "http://host1/file.zip" "ftp://host2/file.zip"

Download files listed in a text file concurrently¶

 aria2c -ifiles.txt -j2

Using a proxy¶
For HTTP:

 aria2c --http-proxy="http://proxy:8080" "http://host/file"
 aria2c --http-proxy="http://proxy:8080" --no-proxy="localhost,127.0.0.1,192.168.0.0/16" "http://host/file"

For FTP:

 aria2c --ftp-proxy="http://proxy:8080" "ftp://host/file"

Note

See --http-proxy, --https-proxy, --ftp-proxy, --all-proxy and --no-proxy for details. You can specify proxy in the environment variables. See ENVIRONMENT section.

Using a Proxy with authorization¶

 aria2c --http-proxy="http://username:password@proxy:8080" "http://host/file"
 aria2c --http-proxy="http://proxy:8080" --http-proxy-user="username" --http-proxy-passwd="password" "http://host/file"

Metalink Download¶
Download files with remote Metalink¶

 aria2c --follow-metalink=mem "http://host/file.metalink"

Download using a local metalink file¶

 aria2c -p --lowest-speed-limit=4000 file.metalink

Note

To stop a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory.

Download several local metalink files¶

 aria2c -j2 file1.metalink file2.metalink

Download only selected files¶

 aria2c --select-file=1-4,8 file.metalink

Note

The index is printed to the console using -S option.

Download a file using a local metalink file with user preference¶

 aria2c --metalink-location=jp,us --metalink-version=1.1 --metalink-language=en-US file.metalink

BitTorrent Download¶
Download files using a remote BitTorrent file¶

 aria2c --follow-torrent=mem "http://host/file.torrent"

Download using a local torrent file¶

 aria2c --max-upload-limit=40K file.torrent

Note

To stop a download, press Ctrl-C. You can resume the transfer later by running aria2c with the same argument in the same directory.

Download using BitTorrent Magnet URI¶

 aria2c "magnet:?xt=urn:btih:248D0A1CD08284299DE78D5C1ED359BB46717D8C&dn=aria2"

Note

Don't forget to quote BitTorrent Magnet URIs which include & characters with single(') or double(") quotes when specifying URIs on the command-line.

Download 2 torrents¶

 aria2c -j2 file1.torrent file2.torrent

Download a file via torrent and HTTP/FTP server in parallel¶

 aria2c -Ttest.torrent "http://host1/file" "ftp://host2/file"

Only download specific files (usually called "selected download")¶

 aria2c --select-file=1-4,8 file.torrent

Note

The index is printed to the console using -S option.

Download a .torrent file, but do not download the torrent¶

 aria2c --follow-torrent=false "http://host/file.torrent"