截屏和录屏命令,外部程序调用

2019-05-03 22:43 来源:未知

之前看到shell命令行,有人写过漫天下字母的cmatrix,想自己动手用python写一个类似,但是比较有自己风格的shell屏保

pycharm简介

前言

在平时写博客的时候,我们经常需要截图,录制视屏,或者制作 gif 动图。今天,我们就依赖来讨论一下有哪些方法。

大致效果如下:

现成的工具软件,都可以完成一些功能(wget下载文件,ffmpeg多媒体视频音频文件的切割,转换、合并视频,录制)

第一种方法:

手机屏幕投影到电脑,在利用电脑上的软件进行截图,录制视频,或者制作 gif 动图。

手机屏幕同步都电脑,我们可以使用 Vysor 这个 chrome 插件,截图我们可以 使用 QQ 截图快捷键 Ctrl Alt A, 制作 gif 动图我们可以使用 gif 转换工具 LICEcap

下载地址

  • 手机屏幕同步到电脑的工具 Vysor ,这是 chrome 插件,需要翻墙

  • 好用的 gif 转换工具 LICEcap ,官网地址,下载地址

 图片 1图片 2图片 3

有时需要扩展一下,添加一点功能(free查看某一固定点内存使用)

第二种方法:

使用 adb 命令。下面让我们一起来看一下怎样使用 adb 命令进行截图。


 

有时需要把工具软件组合起来(free、gnuplot画图表)

adb 截屏命令 screencap

制作这个的大体思路比较简单:

粘合各种外部程序和各种语言的库,实现功能,方法:

第一种方法

//(保存到SDCard)
adb shell /system/bin/screencap -p /sdcard/screenshot.png
// 从SD卡导出到电脑,注意 F:\mvp 为电脑路径,必须存在
adb pull /sdcard/screenshot.png F:\mvp(保存到电脑)

如果你想删除手机上的图片,那么你可以使用这个命令来删除

adb shell rm /sdcard/screen.png

1.利用python的PIL的库,进行图像转换屏幕字母的绘制  

os.system

第二种方法

adb shell screencap -p | sed 's/r$//' > screen.png

需要注意的是,图片会保存在当前 cmd 启动的路径,screen.png 为图片的名字

比如我在 C:UsersAdministrator 执行命令,那么将会保存在 C:UsersAdministrator 目录下。

C:UsersAdministrator>adb shell screencap -p | sed 's/r$//' > screen.png

2.运行此程序,作为一个命令使用

subprocess

扩展

如果你觉得每一次都要输入这么长的命令 adb shell screencap -p | sed 's/r$//' > screen.png ,怕记不住,我们是可以采取一些方法的。那就是用 alias 包装起来,相当于是起别名的意思。

由于 alias 是 linux 特有的命令,我们无法再 windows 使用,如果想在 windows 使用类似的功能,可以参考下面的博客。

在Windows中利用doskey配置类似Linux中alias命令

创建Windows命令行的alias


先说第一步:

调用外部程序

adb 录屏命令 screenrecord

以下是所需要的库:PIL用于绘图,argparse用于给python程序提供入口参数,time用于每个图片的切换间隔

os库里面的system函数,等于打开操作系统的shell,敲入一串命令,比如mspaint 命令

简介

  1. screenrecord 是一个 shell 命令
  2. 支持 Android 4.4(API level 19)以上
  3. 支持视频格式: mp4

一些限制

某些设备可能无法直接录制,原因是分辨率太高,如果遇到此类问题,请试着指定较低的分辨率
不支持录制过程中屏幕旋转,如果录制过程中旋转,有可能画面被切断
录制视频的时候声音不会被录下来


1 from PIL import Image
2 import argparse
3 import time

import os

开始录制命令:

adb shell screenrecord /sdcard/demo.mp4

说明:录制手机屏幕,视频格式为mp4,存放到手机sd卡里,默认录制时间为180s

下面添加所需要的入口参数:这里width,height就是屏幕的宽高

os.system('mspaint')

限制录制时间:

参数: --time-limit

adb shell screenrecord  --time-limit 10 /sdcard/demo.mp4

说明:限制视频录制时间为10s,如果不限制,默认180s

 1 parser = argparse.ArgumentParser()
 2 
 3 parser.add_argument('file')  #input file
 4 parser.add_argument('--width', type = int ,default = 150) #output_string width
 5 parser.add_argument('--height' , type = int , default = 48) #output_string height
 6 
 7 #get args
 8 args = parser.parse_args()
 9 
10 IMG = args.file
11 WIDTH = args.width
12 HEIGHT = args.height

print ('after call')

指定视频分辨率大小:

参数: --size

adb shell screenrecord --size 1280*720 /sdcard/demo.mp4

说明:录制视频,分辨率为1280*720,如果不指定默认使用手机的分辨率,为获得最佳效果,请使用设备上的高级视频编码(AVC)支持的大小

指定视频的比特率

随便定义一个accii:

直到外部程序退出了,代码才接着往下执行

参数: --bit-rate

adb shell screenrecord --bit-rate 6000000 /sdcard/demo.mp4

说明:指定视频的比特率为6Mbps,如果不指定,默认为4Mbps. 你可以增加比特率以提高视频质量或为了让文件更小而降低比特率

ascii_char = list("~!@#$%^&**()-=[];',./_ {}|qwertyuiopasdfghjklzxcvbnmQAZWSXEDCRFVYHIKJMPLH;'./,")

上面的最后一行打印的‘after call’直到我们关闭画笔程序才会接着往下执行

在命令行显示log

参数: --verbose

adb shell screenrecord --time-limit 10 --verbose /sdcard/demo.mp4

输入以上命令,将可以看到这些信息。

Main display is 1080x1920 @59.16fps (orientation=0)
The max width/height supported by codec is 1920x1088
Configuring recorder for 1088x1920 video/avc at 4.00Mbps
Content area is 1080x1920 at offset x=4 y=0
Time limit reached
Encoder stopping; recorded 133 frames in 10 seconds
Stopping encoder and muxer
Executing: /system/bin/am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file:///sdcard/demo.mp4
Broadcasting: Intent { act=android.intent.action.MEDIA_SCANNER_SCAN_FILE dat=file:///sdcard/demo.mp4 }
Broadcast completed: result=0

写RGB转字符的函数:

组装参数

旋转90度

参数: --rotate

说明:此功能为实验性的,好不好用不知道

1 def get_char(r , g , b , alpha=256):
2     #RGB值轉換爲字符值
3     if alpha == 0:
4         return ' '
5     length = len(ascii_char)
6     gray = int (0.2126 *r   0.7152* g   0.0722 * b)   #灰度值計算公式
7     unit = (256.0   1) /length
8     return ascii_char[int(gray/unit)]

工具软件命令行支持参数,组装出相应的参数

查看帮助命令

参数: --help

输入以下命令

adb shell screenrecord --help

将可以看到这些信息。

Usage: screenrecord [options] <filename>

Android screenrecord v1.2.  Records the device's display to a .mp4 file.


Options:
--size WIDTHxHEIGHT
    Set the video size, e.g. "1280x720".  Default is the device's main
    display resolution (if supported), 1280x720 if not.  For best results,
    use a size supported by the AVC encoder.
--bit-rate RATE
    Set the video bit rate, in bits per second.  Value may be specified as
    bits or megabits, e.g. '4000000' is equivalent to '4M'.  Default 4Mbps.
--bugreport
    Add additional information, such as a timestamp overlay, that is helpful
    in videos captured to illustrate bugs.
--time-limit TIME
    Set the maximum recording time, in seconds.  Default / maximum is 180.
--verbose
    Display interesting information on stdout.
--help
    Show this message.

Recording continues until Ctrl-C is hit or the time limit is reached.

写主函数:

import os

导出视频:

adb pull /sdcard/demo.mp4
说明:导出视频到当前目录

到处到指定的目录

adb pull /sdcard/demo.mp4 F:mvpdemo.mp4

 1 if __name__ == '__main__':
 2 
 3     im = Image.open(IMG)
 4     im = im.resize((WIDTH,HEIGHT) , Image.NEAREST)
 5 
 6     txt = ""
 7 
 8     for i in range(HEIGHT):
 9         for j in range(WIDTH):
10             txt  = get_char(*im.getpixel((j,i)))
11         txt  = 'n'
12     
13     print(txt)
14     time.sleep(0.8)

os.system('mspaint e:\1.png')  #打开图片

制作 gif 动图

利用 LICEcap 进行转换。


至此,一个分辨率不高的图片就可以转换成字符形式的了,如下:

print ('after call')

题外话

第一种方法,相对于第二种方法( 使用 adb 命令)来说,在截图和录制视频的时候,效率差不多,而在制作 gif 动图的时候,效率会快得挺多的,那为什么还要讲解 adb 命令呢?

一:让大家知道有更多的方法,开阔视野(哈哈,其实我是在扯蛋);

二:使用 Vysor 投影的时候,有一部分手机不支持,作为不是富二代的我们有时很无奈,不可能说为了能使用 Vysor 进行投影,而去重新买一部手机,这时候就退而求其次,使用 adb 命令了。

三: 作为一名开发人员,我们还是要学一些常用的命令的。这样也可以装装逼。

CSDN文章首发地址

图片 4

组装复杂参数

然后开始第二部分:

ffmpeg

编写如下shell命令:

录制屏幕右上角例子

1 #!/bin/bash
2 while true
3 do
4     python3 ~/pythonFile/xfqz/toPIC.py ~/Pictures/w.jpg
5     python3 ~/pythonFile/xfqz/toPIC.py ~/Pictures/h.jpg
6     python3 ~/pythonFile/xfqz/toPIC.py ~/Pictures/y.jpg
7     python3 ~/pythonFile/xfqz/toPIC.py ~/Pictures/z.jpg
8 done

#coding = utf8

其中,w.jpg,h.jpg,y.jpg,z.jpg,都是网上随便找到的,你也可以自己找,

import time,os

将这个文件另存为whyz.sh

#输出视频文件

在.bashrc进行命令配置:

outputfile = 'd:/data/bandicam/tmp/' time.strftime('%Y%m%d_%H%M%S',time.localtime()) '.mp4'

alias whyz='bash ~/pythonFile/xfqz/whyz.sh'

#工具目录

 注意的事,whyz='命令'   这其中不要有空格,然后,保存退出,

ffmpegDir = r'd:/data/bandicam/tmp/ffmpeg.exe'

再次进入bashshell 就可以得到whyz的炫酷命令了~ 

setting = [

 

  '-y -rtbufsize 100M -f gdigrab -framerate 10'   #帧率等

ps:

  ‘-offset_x 1000 -offset_y 0 -video_size 640*480, #录制指定屏幕区域

在linux在制作gif动图也很简单:

  ‘-draw_mouse 1 -i desktop -c:v libx264’,              #视频编码格式

1.两个工具:一个是simplescreenrecorder用于屏幕录制(其他的屏幕录制软件也可以),一个是ffmpeg,用于将视频格式转换为gif动图格式

  '-r 20 -preset medium -tune zerolatency -crt 35',  #视频压缩参数

使用如下命令

  '-pix_fmt yuv420p -fs 100M -movflags faststart "%s"' %outputfile             #大小限制等

ffmpeg -i input.ogg -s 640x320 -r 15 output.gif    

]

#将参数组合起来

recordingCmdLine = ' '.join([ffmpegDir] setting)

#查看命令内容

print (recordingCmdLine)

#执行命令录制视频

os.system(recordingCmdLine)

返回值

有些程序退出后会有一个退出码

  表示程序是否正确实现了其功能

  Linux的命令 比如 ls ; echo $?(退出码是0,表示命令执行成功)

python在调用这些程序时,退出码作为返回值返回

Windows

  如果是cmd.exe ,返回值就是进程的退出码(退出码为0)

Linux

会返回一个16位数字

低位字节 表示结束进程的信号数值

如果低位字节值为0,高位字节表示退出码       512转换为十六进制,两位代表一个字节   ‘%x’ Q2 -》200,低位0,高位是2;退出码是2

可以通过返回值来判断命令是否执行成功

import os

ret = os.system('cp /opt/file1 /home/hyz/file1')

if ret == 0:

  print ('file copied.')

else:

  print ('copy file failed!!')

subprocess 获取第三方输入内容

subprocess 库里面的check_output

import subprocess

 #shell=True 表示使用终端shell执行程序,Windows下面就是cmd.exe

 #就是我们python程序调用cmd.exe,再由cmd.exe执行参数命令

ret = subprocess.check_output('dir', shell = True,encoding = 'gbk')  encoding不填最终返回byte,填上参数自动解码成Unicode

#如果有中文,需要decode,因为中文os,所以cmd.exe输出是gbk编码

print(ret)

#print (ret.decode('gbk'))

subprocess.check_output 需要等到被调用程序退出,才能返回

subprocess库里面的Popen类,可以:被调用程序运行时候,就获取其输出的信息;运行时,输入一些信息给被调用程序

subprocess.Popen(args,stdin =None,stout = None,stderr = None,shell = False,encoding = None)

args 参数要么是列表,要么是一个字符串 

   popen = Popen(args = ['mspaint',r'e:1.jpg'])

shell = True 表示用shell去执行,args 应该是字符串;

shell = False表示不是用shell去执行,args参数应该是一个列表

非阻塞式调用

非阻塞式调用外部程序

from subprocess import PIPE,Popen

process = Popen(

  args = 'mspaint',

  shell = True

  )

print ('done')

调用外部程序后,python程序继续执行

输入输出重定向

得到外部程序的输出

from subprocess import PIPE,Popen

popen = Popen(

  'dir c:',

  stout = PIPE,    管道,不指定会输入到终端

  shell = True,

  encoding = 'gbk')

output, err = popen.communicate()

print(output)

import time,trackback

try:

  while True:

  num = input('**请输入数字:‘)

  if num.isdigit():

    print('立方是: %s' %int(num)**3)

except:

  print(traceback.format_exc())

 

Popen = Popen(

  'python s4_1.py‘,

  stdin = PIPE ,

  stdout = PIPE,

  stderr = PIPE,

  shell = True,

  encoding = 'utf-8')

inputList = ['3','4','37','55']

out,err = popen.communicate('n'.join(inoutList)               #3回车,4回车,37回车,55  最后自动输入 EOF(end of file)

print(out,err)

 

装饰器

函数里面定义函数

def foo():

  def bar():

    print ('in bar()')  只在函数里使用

  print (‘in foo()’)

  bar()

foo()

执行结果:

in foo()

in bar()

bar 的有效范围:函数内部

在foo()函数外面使用bar()函数的办法:

def foo():

  def bar():

    print ('in bar()') 

  print (‘in foo()’)

  return bar()

inner = foo()          返回bar指向bar()

inner()                   相当于调用bar()

bar是一个函数对象

函数里面定义类

def foo():

  class My():

    pass

  print ('in foo()')

  My()

foo()

My的有效范围:函数内部

定义类的静态的方法时,就使用了装饰器

  @staticmethod

  def jump():

    print ('3 meters high')

装饰器的特点是用一个@开头的字符串

在我们阅读别人的代码时,会经常碰到装饰器

装饰器通常用来装饰函数

装饰器主要用来给函数增加一点功能

一般装饰器本身也是一个函数(callable)

我们可以想象成它包含了被装饰的函数

例子

返回字符串的函数

def hello():

  return 'hello'

def hi():

  return 'hi'

我们需要返回值多两个!

def endsign(func):

  def wrapper():

    return func() '!!'    闭包

  return wrapper

@endsign

def hello():

  return 'hello'

#hell0 = endsign(hello)

print (hello())  调用hello()

有参数的函数

要装饰的函数参数都不同

def endsign(func):

  def wrapper(*args,**kargs):

    print('args:', args)

     print('kargs:',kargs)

    return func((*args,**kargs) '!!'

  return wrapper

@endsign

def hello(arg1,arg2 = ' '):

  return 'hello %s %s ' %(arg1,arg2)

@endsign

def goodbye(targets):

  return 'goodbye %s ' %'  '.join(targets)

装饰器本身带参数

需要的结尾可能不同

@endsign('!!')

def hello(arg1,arg2 = ' '):

  return 'hello %s %s ' %(arg1,arg2)

hello = endsign('!!')

@endsign('??')

def hi(arg1,arg2 = ' ');

  return 'hi %s %s' %(arg1,arg2)

hi = endsign('??')(hi)

 def endsign(tail):

  def innerOne(func):

    def wrapper():

      return func() '  ' tail

    return wrapper

  return innerOne

@enddign('??')

def hello():

  return 'hello'

#hello = endsign('??') (hello)

print (hello())

endsigns('??')(hello) = innerone(hello) = wrapper

补充

我们在写模块文件的时候,对里面的函数往往有些测试代码,调用一下上面写的函数

如果忘了注释掉,在其他模块导入这个模块的时候,就会执行

def sayHello():

  print("hello")

def sayGoodbye():

  print("goodbye")

print (__name__)

if __name__ == "__main__"      __name__只在入口模块执行,作为入口模块才会执行,导入到其他文件后不执行

  print ('exec testing')

  sayHell0()

  sayGoodbye()

可不可以有多个装饰器?可以,定义多个装饰器函数;可以定义多个装饰器修饰一个函数

def endsign(func):

  def wrapper():

    return func() '!!'   

  return wrapper

def endsign2(func):

  def wrapper():

    return func() '##'   

  return wrapper

@endsign2

@endsign 先执行里面的这个

def hello():

  return 'hello'

hello = endsign(hello)

hell0 = endsign2(hello)

print (hello()) 

 

 

  

 

版权声明:本文由韦德娱乐1946_韦德娱乐1946网页版|韦德国际1946官网发布于网络编程,转载请注明出处:截屏和录屏命令,外部程序调用