0%

iOS中圆角对性能的影响

关于圆角设置问题之前一直存在一些讨论,因为面试中碰到面试官问我这个问题,因为自己的项目中一个界面中用到圆角的个数并不多所以我也没有仔细研究过这个问题,这次趁着这次机会测试一下圆角问题。

圆角设置

首先我们通过系统的api去设置圆角imageView.layer.cornerRadius = 10;
通过设置layer的cornerRadius来设置圆角,但是只设置这个虽然说是成功的设置了圆角。但是cornerRadius这个属性只会影响到视图的背景颜色和border。对于UIlabel和UIImageView这样的内部还有其他视图的控件就不能起作用,所以大部分情况下我们还要设置上imageView.layer.masksToBounds = true。这样才能达到我们的预期效果。

性能问题

首先网上查找关于设置圆角的文章,发现之前说的是设置圆角cornerRadius不会触发离屏渲染,设置masksToBounds才会触发离屏渲染,但是并不是只要设置了就会影响性能,只要当涉及到的视图数量够多才会影响性能,使FPS降低。但是我这边测试发现在最新的系统上测试并没有发现性能问题。这里结合代码说明。

首先创建一个TableViewCell中每行放多个设置了圆角的ImageView
cell中创建圆角视图的代码:

然后打开Xcode中的调试工具Instrument然后选择Core Animation

然后调试后发现当我屏幕中出现很多设置了圆角的ImageView的时候这时候的FPS并没有明显降低,维持在60帧左右,没有出现之前的文章中所说的当一个屏幕中出现超过17个左右的视图后FPS会明显下降,我这里测试的手机是iPhone6S系统时iOS12。

然后打开Xcode中关于离屏渲染的调试选项,这里说明一下之前的离屏渲染相关的debug选项都在Instrument中,从Xcode9之后把这个选项集成到了Xcode的debug选项中,查找路径是在Xcode->Debug->View Debugging->Rendering->Color Offscreen Rendered Yellow然后发现并没有触发离屏渲染。可以看出目前我这个视图中已经有超过50个设置了圆角的ImageView,但是并没有影响到FPS。所以关于圆角设置问题我这边认为,只要不是特别特别负责的视图,或者说明显的FPS很低的时候,不用考虑优化问题,直接设置masksToBoundscornerRadius是没有什么问题的。

其他方法设置圆角

为普通的UIView视图设置圆角的思路通过Core Graphics自己画出了一个圆角矩形,返回的是一个image然后创建一个ImageView视图插入到视图层级的底部。这样就完成了圆角的设置。

ImageView设置圆角,思路是获取ImageView的图片,同样通过Core Graphics将image直接截出圆角。

这个思路是参考这篇文章的。详细的代码可以参考这篇文章,iOS 高效添加圆角效果实战讲解

总结

推荐直接使用系统提供的API直接设置圆角,如果测试后针对某些机型或者系统存在特别严重的问题后再针对性的调试后优化,如果界面不是特别复杂,过早的优化是没有太大必要的。

GStreamer使用tee创建分支

可以使用tee命令对一个视频流创建分支。将数据分割成多个数据流的分支。

需要在每个分支中使用单独的队列元素为每个分支提供单独的线程。否则一个分支阻塞数据流会阻塞其他分支

使用场景:捕获视频后,其中一个分支显示在屏幕,另一个分支写入文件。播放音频并且挂载可视化模块

输入源为测试视频、输出为两个流

1
2
3
4
5
6
//tee 测试视频 去掉延时  ----通过
gst-launch-1.0 videotestsrc pattern=pinwheel ! decodebin ! tee name=t ! \
queue ! videoconvert ! x264enc bitrate=1000 tune=zerolatency ! video/x-h264 ! h264parse ! video/x-h264 ! \
queue ! flvmux streamable=true ! rtmpsink location='rtmp://192.168.18.188/live/999' \
t. ! queue ! videoconvert ! x264enc ! flvmux streamable=true ! \
queue ! rtmpsink location='rtmp://192.168.18.188/live/888'

输入源为屏幕、输出为两个流

1
2
3
4
5
6
//tee 屏幕打流 去掉延时  ----通过
gst-launch-1.0 ximagesrc ! decodebin ! tee name=t ! \
queue ! videoconvert ! x264enc bitrate=1000 tune=zerolatency ! video/x-h264 ! h264parse ! video/x-h264 ! \
queue ! flvmux streamable=true ! rtmpsink location='rtmp://192.168.18.188/live/999' \
t. ! queue ! videoconvert ! x264enc ! flvmux streamable=true ! \
queue ! rtmpsink location='rtmp://192.168.18.188/live/888'

输入源为屏幕、输出为两个流(其中一个流加延时)

关键参数:sync=false 设置为不同步否则。出去的两个流都存在延时。

而且一定要把tee的两个分支放在不同的queue中。

1
2
3
4
5
6
gst-launch-1.0 ximagesrc startx=0 use-damage=0 ! decodebin ! tee name=t ! \
queue ! videoconvert ! x264enc bitrate=1000 tune=zerolatency ! video/x-h264 ! h264parse ! video/x-h264 ! \
queue max-size-buffers=0 max-size-bytes=0 max-size-time=90000000000 ! queue max-size-buffers=0 max-size-time=90000000000 min-threshold-time=15000000000 ! \
flvmux streamable=true ! rtmpsink location='rtmp://192.168.18.188/live/999' t. ! \
queue ! videoconvert ! x264enc ! \
queue ! flvmux streamable=true ! rtmpsink location='rtmp://192.168.18.188/live/888' sync=false

Voctomix安装配置过程记录

更新软件源

1
2
apt-get update
apt-get upgrade

nginx编译安装

安装依赖

sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev

下载nginx和rtmp模块源码(这里下载的是1.12.0可以根据需求选择下载)

1
2
wget http://nginx.org/download/nginx-1.12.0.tar.gz
wget https://github.com/arut/nginx-rtmp-module/archive/master.zip

安装解压工具:

1
apt-get install unzip

解压源码:

1
2
tar -zxvf nginx-1.7.5.tar.gz
unzip master.zip

选择进入nginx源码目录:

cd nginx-1.12.0/

编译安装:

1
2
3
./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-master
make
sudo make install

安装Nginx init脚本

1
2
3
sudo wget https://raw.github.com/JasonGiedymin/nginx-init-ubuntu/master/nginx -O /etc/init.d/nginx
sudo chmod +x /etc/init.d/nginx
sudo update-rc.d nginx defaults

nginx配置rtmp:(写在最后面,http外面)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 1935;
chunk_size 4096;
notify_method get;
application live {
live on;


exec /home/www/bin/stream2switcher.sh $name;
exec_kill_signal term;

record off;
#exec ffmpeg -i rtmp://localhost/live/$name -threads 1 -c:v libx264 -profile:v baseline -b:v 350K -s 640x360 -f flv -c:a aac -ac 1 -strict -2 -b:a 56k rtmp://localhost/live360p/$name;
}
application live360p {
live on;
record off;
}
}

重新加载nginx

service nginx reload

正常的话查看端口会发现80端口和1935端口都启动了

安装php7:

1
apt-get -y install php7.0-fpm

配置nginx和php

修改nginx配置文件:

/usr/local/nginx/conf/nginx.conf

修改nginx配置:

1
2
3
4
5
6
location ~ \.php$ {
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}

修改php配置:

vim /etc/php/7.0/fpm/php.ini
找到cgi.fix_pathinfo修改为1

然后重新加载php-fpm

service php7.0-fpm reload

为了测试是否成功我们在www目录下创建一个phpinfo.php文件
vim /home/www/phpinfo.php

1
2
3
4
5
<?php

phpinfo();

?>

然后访问你的http://your ip/phpinfo.php
如果能显示出phpinfo信息就说明正常。
如果提示nginx error的话查看nginx 的error.log根据错误提示修改。

安装MySQL:

1
apt-get install mysql-server mysql-client

设置用户名密码:(默认)

1
2
用户名:root
密码:root

编译安装ffmpeg

Ubuntu下安装ffmpeg和依赖包以及ffmpeg的使用

安装redis与php扩展

apt-get install redis-server

php-redis扩展安装

安装Voctomix

安装依赖

1
2
3
4
5
# Requirements
apt-get install gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-tools libgstreamer1.0-0 python3 python3-gi gir1.2-gstreamer-1.0 gir1.2-gst-plugins-base-1.0

# Optional for the Example-Scripts
apt-get install python3-pyinotify gstreamer1.0-libav rlwrap fbset

如果还要用到GUI还需要安装:

1
apt-get install gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-alsa gstreamer1.0-tools libgstreamer1.0-0 python3 python3-gi python3-gi-cairo gir1.2-gstreamer-1.0 gir1.2-gst-plugins-base-1.0 gir1.2-gtk-3.0

复制项目到指定目录

因为项目中脚本路径问题这里直接放在/home/sun/目录下。如果放在其他目录下记得修改项目中的路径问题。

代码上传后记得给对应的文件添加执行权限。

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
└── home
├── sun
│   ├── voctomix
│   │   ├── Dockerfile
│   │   ├── LICENSE.txt
│   │   ├── README.md
│   │   ├── README_DOCKER.md
│   │   ├── check_pep8.sh
│   │   ├── docker-ep.sh
│   │   ├── example-scripts
│   │   │   ├── README.md
│   │   │   ├── control-server
│   │   │   ├── default-config.sh
│   │   │   ├── ffmpeg
│   │   │   ├── ffmpeg_video_src_config.sh
│   │   │   ├── gstreamer
│   │   │   ├── misc
│   │   │   ├── systemd-units
│   │   │   └── voctomidi
│   │   ├── pushstream.sh
│   │   ├── voctocore
│   │   │   ├── README.md
│   │   │   ├── default-config.ini
│   │   │   ├── lib
│   │   │   └── voctocore.py
│   │   └── voctogui
│   │   ├── README.md
│   │   ├── Shortcut-Cheat-Sheet
│   │   ├── default-config.ini
│   │   ├── lib
│   │   ├── ui
│   │   ├── voctogui.py
│   │   └── voctomix.png
│   └── voctomix-outcasts
│   ├── LICENSE
│   ├── README.md
│   ├── configs
│   │   ├── 360p.ini
│   │   ├── 720p.ini
│   │   ├── lca.ini
│   │   ├── light.ini
│   │   └── test_720p.ini
│   ├── debian
│   │   ├── changelog
│   │   ├── compat
│   │   ├── control
│   │   ├── copyright
│   │   ├── rules
│   │   ├── source
│   │   └── voctomix-outcasts.dirs
│   ├── generate-cut-list.py
│   ├── ingest.py
│   ├── lib
│   │   ├── __pycache__
│   │   └── connection.py
│   ├── record-mixed-av.sh
│   ├── record-timestamp.sh
│   ├── setup
│   │   └── voc_gits_path.sh
│   ├── temp
│   │   └── 111.sh
│   └── tests
│   ├── 360p_pushstream_OK.sh
│   ├── 360p_start_voctomix.sh
│   ├── 720p_pushstream_OK.sh
│   ├── 720p_start_voctomix.sh
│   ├── coupler-server.sh
│   ├── dummy-server-src.sh
│   ├── dummy-server.py
│   ├── mock-stack.sh
│   ├── pushstream_OK.sh
│   ├── server-file.sh
│   ├── test1.sh
│   ├── test2.sh
│   ├── test_720p.sh
│   ├── test_720p_pushstream_OK.sh
│   ├── test_720p_pushstream_OK_bak.sh
│   ├── voctomixstatus.sh
│   ├── voctomixstop.sh
│   └── zcwtest.sh
└── www
├── bin
│   ├── logs
│   │   └── stream2switcher.log
│   └── stream2switcher.sh
├── controller
│   ├── GeneralMethod.php
│   ├── StartVoctomix.php
│   ├── StatusVoctomix.php
│   ├── StopVoctomix.php
│   ├── StreamConfig.php
│   ├── VoctomixConfig.php
│   ├── VoctomixControl.php
│   ├── dbConnect.php
│   ├── dbtest.php
│   ├── httpStatus.php
│   ├── index.php
│   ├── outputStream.php
│   ├── outputStreamConfig.php
│   ├── testapi.php
│   ├── userLogin.php
│   ├── userSignUp.php
│   └── voctomix.php
├── index.php
├── phpinfo.php
└── stat.xsl

通过redis控制流的输入

脚本位置/home/www/bin/stream2switcher.sh

修改nginx中的配置自动调用脚本。

n

这里需要指定输入的流对应相应的端口,这样就可以作为导播台的输入源。

APP控制接口

相关API文档参考

导播台相关API文档

/home/www/controller/

  • StreamConfig.php输入流配置
  • outputStreamConfig.php配置输出流并且启动服务
  • outputStreamConfig.php停止服务

控制接口目前直接使用socket连接的方式去控制

参考地址

Redis安装与使用

php7安装Redis扩展

nginx-rtmp模块编译安装

nginx下载页

cgi.fix_pathinfo的安全隐患

Voctomix项目介绍

简单介绍文档

项目介绍

开源的实时视频混合器

项目名称 项目地址
Voctomix 源码地址

Voctomix是官方项目主要包含三部分代码:

  • Voctocore:实现视频和音频处理的视频处理器核心过程
  • Voctogui:GUI实现,可以控制核心功能,并实时显示视频效果
  • Voctomix Example Scripts:一些脚本实例,包含使用脚本控制视频混合,视音频切换等。
项目名称 项目地址
Voctomix-Outcasts 源码地址

Voctomix-Outcasts是一个快速运行测试的Demo帮我们实现了解Voctomix运行过程。

安装步骤

Voctomix需要一个比较新的GStreamer(至少1.5版本以上,推荐1.6版本)

安装依赖项:

1
2
3
4
5
# Requirements
apt-get install gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-tools libgstreamer1.0-0 python3 python3-gi gir1.2-gstreamer-1.0 gir1.2-gst-plugins-base-1.0

# Optional for the Example-Scripts
apt-get install python3-pyinotify gstreamer1.0-libav rlwrap fbset

如果你想用GUI还需要安装下面的依赖项:

1
apt-get install gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-alsa gstreamer1.0-tools libgstreamer1.0-0 python3 python3-gi python3-gi-cairo gir1.2-gstreamer-1.0 gir1.2-gst-plugins-base-1.0 gir1.2-gtk-3.0

关于cpu的使用情况,如果想用默认配置1920*1080、25fps,建议使用四核cpu,可以根据配置信息中的分辨率和帧率,选择合适的cpu。建议GUI和core运行在同一台机器上。不然会产生很高的流量。

项目使用介绍

voctocore

块级图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
17000… VSource** (Stream-Blanker) ---\
18000 ASource** (Stream-Blanker) ----\
\
16000 VSource (Background) \
\ \
--> VideoMix \
/ \ -> StreamBlanker** -> StreamOutputPort** 15000
/ \ /
/ ------> OutputPort 11000
/ / \-> Encoder* -> PreviewPort* 12000
/ /
/----- -> AudioMix
/
10000… AVSource --> MirrorPort 13000…
\-> Encoder* -> PreviewPort* 14000…

9999 Control-Server
9998 GstNetTimeProvider Network-Clock

*) only when [previews] enabled=true is configured
**) only when [stream-blanker] enabled=true is configured

网络端口列表

  • 10000,10001,···-主视频源,取决于配置的视频源数量
  • 16000 混音器
  • 17000,17001,···-Stream-Blanker视频输入,取决于配置的Stream-Blanker-Sources的数量
  • 18000 – Stream-Blanker Audio-Input
  • 9999 -接收控制协议连接

GStreamer添加流延时操作

手动添加直播流延时,延时时间可以控制。输入源为测试视频、桌面截屏、rtmp视频流

测试视频测试通过

1
2
3
4
5
6
//默认的几种模式 videotestsrc  延时通过 音频也通过 \
gst-launch-1.0 videotestsrc is-live=true ! videoconvert ! x264enc bitrate=1000 tune=zerolatency ! video/x-h264 ! h264parse ! video/x-h264 ! \
queue ! flvmux name=mux ! \
queue max-size-buffers=0 max-size-bytes=0 max-size-time=90000000000 ! queue max-size-buffers=0 max-size-time=90000000000 min-threshold-time=6000000000 ! \
rtmpsink location='rtmp://192.168.18.188/live/999' \
audiotestsrc is-live=true ! audioconvert ! audioresample ! audio/x-raw,rate=48000 ! voaacenc bitrate=96000 ! audio/mpeg ! aacparse ! audio/mpeg, mpegversion=4 ! mux.

输入源为videotestsrc,包括多种模式显示不同视频。输入不同视频的时候在videotestsrc后面跟上参数pattern=snow,可以选择不听的图案,集体包括那些图案参考官方文档。

videotestsrc官方文档

flvmux将不同的流复合到flv文件中,这里是将不同的流混合后输出为rtmp流,可以理解为音频流和视频流的混合。

videoconvert后面跟的是视频格式

flvmux name=mux后面的是添加延时的操作。

1
2
queue max-size-buffers=0 max-size-bytes=0 max-size-time=$MAX_DELAY ! \
queue max-size-time=$SMALL_DELAY min-threshold-time=$DELAY
  • $DELAY = 延时时间
  • $MAX_DELAY = 最多延时时间
  • $SMALL_DELAY = 最小延时时间

测试后发现,$DELAY是起作用的参数。

该策略是具有两个队列,其中第一个作为缓冲区,第二个队列作为一个平衡器,确保所有消息都被精确延迟$DELAY时间。 这不能使用一个队列来完成。

当需要更改延迟时,$DELAY值将在第二个队列中更改。 之后,管道需要使用新的延迟作为延迟发送延迟事件。 这会导致流水线冻结一段时间(如果延迟增加),或快速向前追赶(如果延迟减少)。

通过读取第一个队列上的当前级别时间属性并将其与设置的延迟进行比较,可以获得缓冲状态。

stackoverflow参考资料

rtmpsink:是把视频流达到后面的rtmp地址上去。

这里的Sink Element是媒体处理pipline的终点。可以理解成最后收集媒体流的地方。

更多资料参考rtmpsink官方文档

audiotestsrc这里和video类似,都是测试用的。

截取屏幕打流测试通过

1
2
3
4
5
6
//屏幕打流延时 15秒延时 通过 加上音频也通过
gst-launch-1.0 ximagesrc startx=0 use-damage=0 ! \
videoconvert ! x264enc bitrate=1000 tune=zerolatency ! video/x-h264 ! h264parse ! video/x-h264 ! \
queue ! flvmux name=mux ! queue max-size-buffers=0 max-size-bytes=0 max-size-time=90000000000 ! queue max-size-buffers=0 max-size-time=90000000000 min-threshold-time=15000000000 ! \
rtmpsink location='rtmp://192.168.18.188/live/999' \
audiotestsrc is-live=true ! audioconvert ! audioresample ! audio/x-raw,rate=48000 ! voaacenc bitrate=96000 ! audio/mpeg ! aacparse ! audio/mpeg, mpegversion=4 ! mux.

拉取rtmp流打流到新的地址测试通过(不加延时)

1
2
//拉取rtmp流不加延时通过   decodebin 要加这个 然后音视频合并
gst-launch-1.0 -v rtmpsrc location=rtmp://192.168.18.188/live/1 ! decodebin ! x264enc bitrate=1000 tune=zerolatency ! video/x-h264 ! h264parse ! video/x-h264 ! ! flvmux ! rtmpsink location='rtmp://192.168.18.188/live/999'

拉取rtmp流打流到新的地址测试通过(加延时无音频)

1
2
3
4
5
6
// 拉取rtmp流加延时 通过
gst-launch-1.0 -v rtmpsrc location=rtmp://192.168.18.188/live/1 !
decodebin ! videoconvert ! x264enc bitrate=1000 tune=zerolatency ! video/x-h264 ! h264parse ! video/x-h264 !
queue ! flvmux streamable=true !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=90000000000 ! queue max-size-buffers=0 max-size-time=90000000000 min-threshold-time=15000000000 !
rtmpsink location='rtmp://192.168.18.188/live/999'

拉取rtmp流打流到新地址测试通过(有延时音频同步)

1
2
3
4
5
6
//rtmp输入 视频 音频 flvdemux 后 flvmux 然后添加延时。 测试通过 
gst-launch-1.0 rtmpsrc location=rtmp://192.168.18.188/live/1 ! \
flvdemux name=mydemuxer flvmux name=mymuxer ! \
queue max-size-buffers=0 max-size-bytes=0 max-size-time=90000000000 ! queue max-size-buffers=0 max-size-time=90000000000 min-threshold-time=15000000000 !
queue ! rtmpsink location=rtmp://192.168.18.188/live/999 \
mydemuxer.audio ! queue ! mymuxer.audio mydemuxer.video ! queue ! mymuxer.video

intervideosrc和intervideosink的使用总结

保证视频流不断的方法

输入视频为MP4

1
2
3
4
//输入MP4 视音频分离 单独处理  成功 intervideosink

gst-launch-1.0 filesrc location=1.mp4 ! qtdemux name=demux \
demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! intervideosink channel=c1 intervideosrc channel=c1 ! queue ! xvimagesink

命令分析:

  • filesrc:输入源为文件
  • qtdemux:MP4文件要用qtdemux分离视频和音频

分离视音频和单独处理视频。然后把分离后的视频当做src,intervideosink channel=c1用来接收到分离后的视频。然后再把intervideosrc channel=c1当做src,xvimagesink用来接收intervideosrc的数据源。这样当你的filesrc断掉的话intervideosrc并不会断掉,这样就保证了断流的安全。没流的情况下会继续播放黑屏,而不是程序崩溃。

注意

demux后分别处理视音频的时候要decodebin然后在执行videoconvert、videoscale的操作。

videomixer结合intervideosrc和sink保证不断流测试

测试通过 一个输入源为文件视频另外一个为文件视频流:测试通过 输出在屏幕上

1
2
3
4
5
gst-launch-1.0 filesrc location=1.mp4 ! qtdemux name=demux1 demux1.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! intervideosink channel=c1 intervideosrc channel=c1 ! \
video/x-raw,format =I420, framerate=25/1, width=1280, height=720 ! \
videomixer name=mix sink_0::alpha=1 sink_0::xpos=0 sink_0::ypos=0 sink_1::alpha=0.3 sink_1::xpos=150 sink_1::ypos=150 ! videoconvert ! timeoverlay ! ximagesink \
filesrc location=1.mp4 ! qtdemux name= demux2.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! intervideosink channel=c2 intervideosrc channel=c2 ! \
video/x-raw,format=I420, framerate=25/1, width=1280, height=720 ! mix.

测试通过 一个输入源为文件视频另外一个为文件视频流:测试通过 输出在rtmp上

1
2
3
4
5
gst-launch-1.0 filesrc location=1.mp4 ! qtdemux name=demux1 demux1.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! intervideosink channel=c1 intervideosrc channel=c1 ! \
video/x-raw,format =I420, framerate=25/1, width=1280, height=720 ! \
videomixer name=mix sink_0::alpha=1 sink_0::xpos=0 sink_0::ypos=0 sink_1::alpha=0.3 sink_1::xpos=150 sink_1::ypos=150 ! videoconvert ! timeoverlay ! x264enc ! flvmux streamable=true ! queue ! rtmpsink location='rtmp://192.168.18.188/live/888' \
filesrc location=1.mp4 ! qtdemux name=demux2 demux2.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! intervideosink channel=c2 intervideosrc channel=c2 ! \
video/x-raw,format=I420, framerate=25/1, width=1280, height=720 ! mix.

修改视频分辨率

1
2
3
4
5
gst-launch-1.0 filesrc location=1.mp4 ! qtdemux name=demux1 demux1.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! videorate ! video/x-raw,format =I420, framerate=25/1, width=640, height=360 ! intervideosink channel=c1 intervideosrc channel=c1 ! \
video/x-raw,format =I420, framerate=25/1, width=640, height=360 ! \
videomixer name=mix sink_0::alpha=1 sink_0::xpos=0 sink_0::ypos=0 sink_1::alpha=0.3 sink_1::xpos=150 sink_1::ypos=150 ! videoconvert ! timeoverlay ! ximagesink \
filesrc location=1.mp4 ! qtdemux name= demux2.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! intervideosink channel=c2 intervideosrc channel=c2 ! \
video/x-raw,format=I420, framerate=25/1, width=1280, height=720 ! mix.
1
2
3
4
5
6

gst-launch-1.0 filesrc location=1.mp4 ! qtdemux name=demux1 demux1.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! videorate ! video/x-raw,format =I420, framerate=25/1, width=640, height=360 ! intervideosink channel=c1 intervideosrc channel=c1 ! \
video/x-raw,format =I420, framerate=25/1, width=640, height=360 ! \
videomixer name=mix sink_0::alpha=1 sink_0::xpos=0 sink_0::ypos=0 sink_1::alpha=0.3 sink_1::xpos=150 sink_1::ypos=150 ! videoconvert ! videoscale ! videorate ! video/x-raw,format =I420, framerate=25/1, width=1920, height=1080 ! timeoverlay ! x264enc ! flvmux streamable=true ! queue ! rtmpsink location='rtmp://192.168.18.188/live/888' \
filesrc location=1.mp4 ! qtdemux name= demux2.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! intervideosink channel=c2 intervideosrc channel=c2 ! \
video/x-raw,format=I420, framerate=25/1, width=1280, height=720 ! mix.

videorate用来改变视频分辨率。后面跟video/x-raw,format =I420, framerate=25/1, width=640, height=360然后保证intervideosrc作为videomixer的输入的时候也要保证相同的分辨率。

GStreamer中videomixer

Videomixer可以接受YUV,ARGB和BGRA视频流。
对于每个请求的接收器,它将比较输入流的几何(画面分辨率)和帧率用来定义输出参数。
实际上输出视频流的参数具有输入视频流中最大的几何(画面分辨率)和最高的帧率。

Videomixer会对色彩空间进行装换

可以在GstVideoMixer2Pad上配置每个输入流的各个参数。

pipeline 例子

1
2
3
4
5
6
7
8
gst-launch-1.0 \
videotestsrc pattern=1 ! \
video/x-raw,format=AYUV,framerate=\(fraction\)10/1,width=100,height=100 ! \
videobox border-alpha=0 top=-70 bottom=-70 right=-220 ! \
videomixer name=mix sink_0::alpha=0.7 sink_1::alpha=0.5 ! \
videoconvert ! xvimagesink \
videotestsrc ! \
video/x-raw,format=AYUV,framerate=\(fraction\)5/1,width=320,height=240 ! mix.

效果说明:

测试视频一是雪花。因为视频一外有一个videobox。

视频二就是后面的背景。

参数说明

  • videotestsrc :测试视频源
  • videobox :视频盒子

videotestsrc

videotestsrc元素用于生成各种格式的测试视频数据。 所产生的视频测试数据可以通过“pattern”属性进行控制。

1
gst-launch-1.0 -v videotestsrc pattern=snow ! video/x-raw,width=1280,height=720 ! autovideosink

通过控制pattern可以控制视频样式:

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
GST_VIDEO_TEST_SRC_SMPTE
A standard SMPTE test pattern

GST_VIDEO_TEST_SRC_SNOW
Random noise

GST_VIDEO_TEST_SRC_BLACK
A black image

GST_VIDEO_TEST_SRC_WHITE
A white image

GST_VIDEO_TEST_SRC_RED
A red image

GST_VIDEO_TEST_SRC_GREEN
A green image

GST_VIDEO_TEST_SRC_BLUE
A blue image

GST_VIDEO_TEST_SRC_CHECKERS1
Checkers pattern (1px)

GST_VIDEO_TEST_SRC_CHECKERS2
Checkers pattern (2px)

GST_VIDEO_TEST_SRC_CHECKERS4
Checkers pattern (4px)

GST_VIDEO_TEST_SRC_CHECKERS8
Checkers pattern (8px)

GST_VIDEO_TEST_SRC_CIRCULAR
Circular pattern

GST_VIDEO_TEST_SRC_BLINK
Alternate between black and white

GST_VIDEO_TEST_SRC_SMPTE75
SMPTE test pattern (75% color bars)

GST_VIDEO_TEST_SRC_ZONE_PLATE
Zone plate

GST_VIDEO_TEST_SRC_GAMUT
Gamut checking pattern

GST_VIDEO_TEST_SRC_CHROMA_ZONE_PLATE
Chroma zone plate

GST_VIDEO_TEST_SRC_SOLID
A solid color, defined by the “foreground-color” property

GST_VIDEO_TEST_SRC_BALL
Moving ball

GST_VIDEO_TEST_SRC_SMPTE100
SMPTE test pattern (100% color bars)

GST_VIDEO_TEST_SRC_BAR
Bar with foreground color

GST_VIDEO_TEST_SRC_PINWHEEL
Pinwheel

GST_VIDEO_TEST_SRC_SPOKES
Spokes

GST_VIDEO_TEST_SRC_GRADIENT
Gradient

GST_VIDEO_TEST_SRC_COLORS
All colors

个别样式

  • pattern=gamut

  • pattern=colors

  • pattern=pinwheel

videobox

此插件裁剪或放大图像。它需要4个值作为输入,顶部,底部,左侧和右侧偏移量。正值将从图像的相应边框裁剪出许多像素,负值将添加很多像素。添加像素时,可以指定其颜色。一些预定义的颜色可用于枚举属性。

该插件是可以设置Alpha通道的。当alpha通道处于活动状态时,可以使用alpha和border_alpha来分别设置内部图片和边框的alpha值。 alpha值为0.0表示总透明度,1.0是不透明的。

视频盒插件有许多用途,如做马赛克的图片,信箱视频(就是所说的宽屏幕视频),剪辑视频,画中画等。

将autocrop设置为true会更改插件的行为,以便帽子确定裁剪属性而不是其他方式:给定的输入和输出尺寸,裁剪值被选中,以便较小的框架在较大的框架中有效居中。这涉及裁剪或填充。

如果您使用自动裁剪,手动设置其他属性将不会有任何意义,因为如果大小更改会覆盖其他属性,但没有任何操作可以阻止您执行此操作。

pipeline 例子

1
gst-launch-1.0   videotestsrc pattern=1 !   video/x-raw,format=AYUV,framerate=\(fraction\)10/1,width=100,height=100 !   videobox border-alpha=1 top=-20 bottom=-20 right=-220 !   videoconvert ! xvimagesink

1
gst-launch-1.0   videotestsrc pattern=1 !   video/x-raw,format=AYUV,framerate=\(fraction\)10/1,width=100,height=100 !   videobox border-alpha=1 top=-70 bottom=-50 right=-220 !   videoconvert ! xvimagesink

对比:

通过对比可以看到参数的意义。

GStreamer中audiomixer

GStreamear中audiomixer允许合并多路输出流。与叠加器不同可以同步所以输入流。但是这里的混合原理还是不算了解。不同频率的音频合并原理?

测试

首先测试频率为100的音频:

1
gst-launch-1.0 audiotestsrc freq=100 ! alsasink

然后测试频率为500的音频:

1
gst-launch-1.0 audiotestsrc freq=500 ! alsasink

然后测试混合音频:

1
gst-launch-1.0 audiotestsrc freq=100 ! audiomixer name=mix ! audioconvert ! alsasink audiotestsrc freq=500 ! mix.

混合后的音频感觉频率处在100和500之间但是。具体多大不了解。

audiotestsrc

测试音频可以产生基本的音频信号,可以提供不同的波形,可以设置不同的频率和音量。

例子(Example)

1
gst-launch-1.0 audiotestsrc ! audioconvert ! autoaudiosink

这个pipeline默认产生了默认频率40Hz默认音量为0.8的正弦波。

1
gst-launch-1.0 audiotestsrc wave=2 freq=200 ! tee name=t ! queue ! audioconvert ! autoaudiosink t. ! queue ! audioconvert ! libvisual_lv_scope ! videoconvert ! autovideosink

这个pipeline是生成锯波。 波形显示使用libvisual的展示给显示器,让您可视化地验证锯波是否正确。

audiotestsrc波形

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
GST_AUDIO_TEST_SRC_WAVE_SINE
a sine wave

GST_AUDIO_TEST_SRC_WAVE_SQUARE
a square wave

GST_AUDIO_TEST_SRC_WAVE_SAW
a saw wave

GST_AUDIO_TEST_SRC_WAVE_TRIANGLE
a tringle wave

GST_AUDIO_TEST_SRC_WAVE_SILENCE
silence

GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE
white uniform noise

GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE
pink noise

GST_AUDIO_TEST_SRC_WAVE_SINE_TAB
sine wave using a table

GST_AUDIO_TEST_SRC_WAVE_TICKS
periodic ticks

GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE
white (zero mean) Gaussian noise; volume sets the standard deviation of the noise in units of the range of values of the sample type, e.g. volume=0.1 produces noise with a standard deviation of 0.1*32767=3277 with 16-bit integer samples, or 0.1*1.0=0.1 with floating-point samples.

GST_AUDIO_TEST_SRC_WAVE_RED_NOISE
red (brownian) noise

GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE
spectraly inverted pink noise

GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE
spectraly inverted red (brownian) noise

Argparse Tutorial

这篇教程简明地介绍了Python标准库推荐使用的命令行参数解析模块——Argparse的使用

注意 还有两个完成相同任务的其他模块,即getopt (与C语言相当的getopt() )和已弃用的optparse 。 还要注意, argparse基于optparse ,因此在使用方面非常相似。

概念

让我们来看看我们将在本入门教程中使用ls命令的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ ls
cpython devguide prog.py pypy rm-unused-function.patch
$ ls pypy
ctypes_configure demo dotviewer include lib_pypy lib-python ...
$ ls -l
total 20
drwxr-xr-x 19 wena wena 4096 Feb 18 18:51 cpython
drwxr-xr-x 4 wena wena 4096 Feb 8 12:04 devguide
-rwxr-xr-x 1 wena wena 535 Feb 19 00:05 prog.py
drwxr-xr-x 14 wena wena 4096 Feb 7 00:59 pypy
-rw-r--r-- 1 wena wena 741 Feb 18 01:01 rm-unused-function.patch
$ ls --help
Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
...

基础

让我们开始一个简单的例子(它什么也没做)

1
2
3
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()

以下是运行代码的结果:

1
2
3
4
5
6
7
8
9
10
11
12
$ python3 prog.py
$ python3 prog.py --help
usage: prog.py [-h]

optional arguments:
-h, --help show this help message and exit
$ python3 prog.py --verbose
usage: prog.py [-h]
prog.py: error: unrecognized arguments: --verbose
$ python3 prog.py foo
usage: prog.py [-h]
prog.py: error: unrecognized arguments: foo

运行结果分析:

  • 不提供参数运行这个脚本,不会输出任何东西
  • 第二步显示了argparse的好处,你什么也没做,却得到了一个很好的帮助信息。
  • –help可以简写成-h,可以得到帮助信息

介绍位置参数

例子:

1
2
3
4
5
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo")
args = parser.parse_args()
print(args.echo)

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ python3 prog.py
usage: prog.py [-h] echo
prog.py: error: the following arguments are required: echo
$ python3 prog.py --help
usage: prog.py [-h] echo

positional arguments:
echo

optional arguments:
-h, --help show this help message and exit
$ python3 prog.py foo
foo

运行分析:

  • 我们添加了add_argument()方法,这个方法是我们用来指定程序接受的哪些命令行选项。 在这种情况下,我将其命名为echo,使其符合其功能。
  • 现在调用我们的程序要求我们指定一个参数。
    parse_args()方法实际上从指定的选项返回一些数据,在这种情况下为echo。
  • 该变量argparse自动执行的的(即不需要指定该值存储在哪里)。 您还会注意到它的名称与给定的方法echo的字符串参数匹配。

补充需要输入一个参数。然后脚本输出这个参数。

尽管自动产生的信息已经很友好,但是我们仍然不能知道参数的具体信息。

1
2
3
4
5
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()
print(args.echo)

运行:

1
2
3
4
5
6
7
8
$ python3 prog.py -h
usage: prog.py [-h] echo

positional arguments:
echo echo the string you use here

optional arguments:
-h, --help show this help message and exit

现在,在做一些更有意义的事:

1
2
3
4
5
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", help="display a square of a given number")
args = parser.parse_args()
print(args.square**2)

运行结果:

1
2
3
4
5
$ python3 prog.py 4
Traceback (most recent call last):
File "prog.py", line 5, in <module>
print(args.square**2)
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

脚本运行出错。因为默认情况下,argparse会把给他的选项视为字符串。所以我们应该对类型进行另外的说明。告诉argparse把输入的参数视为整数:

1
2
3
4
5
6
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", help="display a square of a given number",
type=int)
args = parser.parse_args()
print(args.square**2)

运行代码查看结果:

1
2
3
4
5
$ python3 prog.py 4
16
$ python3 prog.py four
usage: prog.py [-h] square
prog.py: error: argument square: invalid int value: 'four'

运行成功,而且可以检测非法输入。

介绍可选参数

2017年07月07日16:12:05
后面继续翻译
https://docs.python.org/3/howto/argparse.html#id1

中文https://blog.ixxoo.me/argparse.html

下载GooglePlay中应用的apk文件

下载Google Play中应用的apk

想要下载原生的Google Play中应用但是电脑打开了Google Play却不能直接下载apk文件。使用APK Downloader这个网站,或者使用Direct APK Downloader这个插件。

使用APK Downloader网站下载

复制Google Play中应用的地址到APK Downloader网站中,可以获取下载地址。

安装Direct APK Downloader插件

需要你的google play账号信息和设备ID

镜像网站

直接去下面的网站搜索下载:

https://www.apkmirror.com/