基础概念

协程:是一种比线程更加轻量级的存在,协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)。
这样带来的好处就是性能得到了很大的提升,不会像线程切换那样消耗资源。

子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用 了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。
所以子程序调用是通过栈实现的,一 个线程就是执行一个子程序。子程序调用总是一个入口,一次返回,调用顺序是明确的。而协程的调用和子程序不同。

协程在子程序内部是可中断的,然后转而执行别的子程序,在适当的时候再返回来接着执行。

协程的特点在于是一个线程执行,那和多线程比,协程有何优势?

Read More

字符编码

ASCII 码

计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有 0 和 1 两种 状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。
也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000 到 11111111 。

上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码,一直沿用至今。

ASCII 码一共规定了128个字符的编码,比如空格 SPACE 是32(二进制 00100000 ),大写的字母 A 是65(二进制 01000001 )。这128个符号(包括32个不能打印出来的控制符号),只占用了一
个字节的后面7位,最前面的一位统一规定为 0 。

Unicode

Unicode 只是一个符号集。Unicode可以容纳100多万个符号。他规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。比如,汉字的Unicode是十六进制数 4E25 ,转换成二进制数足足有15位
( 100111000100101 ),也就是说,这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。

UTF-8

UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号, 根据不同的符号而变化字节长度。

Read More

按键精灵的使用记录

最近因为工作需要,研究了下按键精灵和相关生态。按键精灵的主要功能是模拟用户行为,可以导出Android、iOS的包。直接在手机上运行。大致猜测下实现原理:

  • 电脑上通过用户的脚本,转换成相关指令,在电脑上的脚本应该通过adb相关指令来控制模拟器或者手机,到处的apk应该是通过调用系统的相关命令(sendevent等)来实现的。
  • 图片检测像素检测应该是通过opencv相关库来实现的。
  • 脚本的编写也是蹲守基本的编程规则,基本的运算、流程控制、多线程,不过还不够完善。
Read More

FFMpeg常用命令

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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

#格式转换
ffmpeg -i input.avi output.mp4
ffmpeg -i input.mp4 output.ts

#提取音频
ffmpeg -i input.mp4 -acodec copy -vn output.aac

#提取视频
ffmpeg -i input.mp4 -vcodec copy -an output.mp4

#视频剪切 -ss表示开始时间 -t表示长度
ffmpeg -ss 00:00:00 -t 00:00:10 -i input.mp4 -vcodec copy -acodec copy output.mp4

#码率控制 bitrate=filesize/duration,比如一个文件20.8M,时长1分钟,那么,码率就是:
biterate = 20.8M bit/60s = 20.8*1024*1024*8 bit/60s= 2831Kbps
一般音频的码率只有固定几种,比如是128Kbps,那么,video的就是:video biterate = 2831Kbps -128Kbps = 2703Kbps。
ffmpeg -i input.mp4 -b:v 2000k output.mp4
ffmpeg -i input.mp4 -b:v 2000k -bufsize 2000k output.mp4 # 官方建议加上-bufsize,用于设置码率控制缓冲器的大小
ffmpeg -i input.mp4 -b:v 2000k -bufsize 2000k -maxrate 2500k output.mp4 # -minrate -maxrate 最小最大范围

#视频编码格式转换
ffmpeg -i input.mp4 -vcodec h264 output.mp4 #使用h264编码
ffmpeg -i input.mp4 -vcodec mpeg4 output.mp4 #使用mpeg4编码

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

#添加水印
ffmpeg -i input.mp4 -i logo.png -filter_complex overlay output.mp4
ffmpeg -i input.mp4 -i logo.png -filter_complex overlay=W-w output.mp4 #右上角
ffmpeg -i input.mp4 -i logo.png -filter_complex overlay=0:H-h output.mp4 #左下角
ffmpeg -i input.mp4 -i logo.png -filter_complex overlay=W-w:H-h output.mp4 #右下角

#去掉logo
有时候,下载了某个网站的视频,但是有logo很烦,咋办?有办法,用ffmpeg的delogo过滤器。
语法:-vf delogo=x:y:w:h[:t[:show]]
x:y 离左上角的坐标
w:h logo的宽和高
t: 矩形边缘的厚度默认值4
show:若设置为1有一个绿色的矩形,默认值0。
ffmpeg -i input.mp4 -vf delogo=0:0:220:90:100:1 output.mp4

#从视频中获取指定尺寸的缩略图, -ss参数要在-i参数之前
ffmpeg.exe -ss 2672 -i input.mkv -y -f mjpeg -t 0.01 -s 96x54 U:/xiaodao/src/temp/xxx.jpg

#将gif转成mp4
ffmpeg -f gif -i origin.gif -pix_fmt yuv420p output.mp4


#使用基于GDI的抓屏设备
ffmpeg -f gdigrab -i desktop out.mpg

#从屏幕的(10,20)点处开始,抓取640x480的屏幕,设定帧率为5
ffmpeg -f gdigrab -framerate 5 -offset_x 10 -offset_y 20 -video_size 640x480 -i desktop out.mpg

#设置帧率
ffmpeg -i input.avi -r 29.97 output.mpg

#码率 ABR、CBR、VBR
ffmpeg -i film.avi -b 1.5M film.mp4
ffmpeg -i file.avi -b:v 1500k output.mp4

设置输出文件最大大小
ffmpeg -i input.avi -fs 10MB output.mp4

文件大小计算
video_size = video_bitrate * time_in_seconds / 8
如果音频没有压缩:
audio_size = sampling_rate * bit_depth * channels * time_in_seconds / 8
压缩音频的文件:
audio_size = bitrate * time_in_seconds / 8

缩放视频
ffmpeg -i input_file -s 320x240 output_file
高级缩放 scale=width:height[:interl={1|-1}]
ffmpeg -i input.mpg -vf scale=320:240 output.mp4
根据输入来设置缩放大小
ffmpeg -i input.mpg -vf scale=iw/2:ih*0.9


裁剪视频 crop=ow[:oh[:x[:y[:keep_aspect]]]]
从左上角裁剪,宽度为原始尺寸的一半,高宽跟原始尺寸一样
ffmpeg -i input -vf crop=iw/2:ih:0:0 output

移动视频 pad=width[:height[:x[:y[:color]]]]
ffmpeg -i photo.jpg -vf pad=860:660:30:30:pink framed_photo.jpg
将视频比例从4:3转为16:9
ffmpeg -i input -vf pad=ih*16/9:ih:(ow-iw)/2:0:color output

翻转和旋转视频
水平翻转
ffplay -f lavfi -i testsrc -vf hflip
旋转 transpose={0, 1, 2, 3}
ffplay -f lavfi -i smptebars -vf transpose=2, vflip

画中画
ffmpeg -i input1 -i input2 -filter_complex overlay=x:y output
水印在右下角
ffmpeg -i pair.mp4 -i logo.png -filter_complex overlay=W-w:H-h pair1.mp4
指定水印开始的时间
ffmpeg -i video_width_timer.mp4 -itsoffset 5 -i logo.png -filter_complex overlay timer_width_logo.mp4

修改速度
ffplay -i input.mpg -vf setpts=PTS/3
快放2倍,取值范围0.5-2.0
ffplay -i speech.mp3 -af atempo=2


创建元数据 -metadata 后面跟键值对
ffmpeg -i input -metadata artist=FFmpeg -metadata title="test" output
保存元数据到文件
ffmpeg -i video.wmv -f ffmetadata data.txt
删除元数据
ffmpeg -i input.avi -map_metadata -l output.mp4

截图
ffmpeg -i videoclip.avi -ss 01:23:45 image.jpg

获取gif动画
ffmpeg -i promotion.swf -pix_fmt rgb24 promotion.gif

根据图片创建视频
ffmpeg -loop l -i photo.jpg -t 10 photo.mp4

根据多张图片生成视频
ffmpeg -f image2 -i img%d.jpg -r 25 video.mp4

播放rtmp
ffplay "rtmp://live.hkstv.hk.lxdns.com/live/hks"

保存直播流
ffmpeg -i http://60.199.188.151/HLS/WG_ETTV-N/index.m3u8 -c:v copy -c:a copy -bsf:a aac_adtstoasc d:\cap.mp4

从视频中抽离部分生成webp
ffmpeg -t 3 -ss 00:00:01 -i ${video_path} -vf scale=320:-1 -q:v 50 -r 10 -compression_level 6 -vcodec libwebp -loop 0 ${output_path}

从视频中提取关键帧图片
ffmpeg -i video_name.mp4 -vf select='eq(pict_type\,I)' -vsync 2 -s 1920*1080 -f image2 keyframe-%02d.jpeg


计算视频的时长
ffmpeg -i source.mp4 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//

合并两个视频
实用文件的方式:
1. 编写filetext.txt文件
file ‘a.mp4’
file ‘b.mp4’
2. 执行命令
ffmpeg -f concat -i filelist.txt -c copy output.mp4
直接用命令行
ffmpeg -i “concat:a.mp4|b.mp4" -c copy output.mp4

IO多路复用

发展史

开始的时候,为了实现一个服务器可以支持多个客户端连接,人们想出了fork/thread等办法,当一个连接来到的时候,就fork/thread一个进程/线程去接收并且处理请求。

到了80年代,计算机网络开始成型,越来越多的用户进行网络连接,但是之前的fork/thread模型在高并发场景快不行了。1983年,发明了select。

对应的编程模型就是:一个连接来了,就必须遍历所有已经注册的文件描述符,来找到那个需要处理信息的文件描述符,如果已经注册了几万个文件描述符,那会因为遍历这些
已经注册的文件描述符,导致cpu爆炸。

到2002年,epoll出现了,于Linux 2.5.44首度登场。

基本概念

用户空间/内核空间

操作系统的核心是内核,为了保证用户进程不能直接操作内核(kernel),保证内核的安全,操作系统将虚拟空间划分为两部分。

Read More