-
Notifications
You must be signed in to change notification settings - Fork 8
/
android_screen_record.py
executable file
·118 lines (93 loc) · 3.84 KB
/
android_screen_record.py
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
#!/usr/bin/env python
# TODO
# This program will use FFMPEG
#
#Writing
#
# To write a series of frames of size 460x360 into the file
# 'my_output_videofile.mp4', we open FFMPEG and indicate that raw RGB data is
# going to be piped in:
#
#command = [ FFMPEG_BIN,
# '-y', # (optional) overwrite output file if it exists
# '-f', 'rawvideo',
# '-vcodec','rawvideo',
# '-s', '420x360', # size of one frame
# '-pix_fmt', 'rgb24',
# '-r', '24', # frames per second
# '-i', '-', # The imput comes from a pipe
# '-an', # Tells FFMPEG not to expect any audio
# '-vcodec', 'mpeg'",
# 'my_output_videofile.mp4' ]
#
# pipe = sp.Popen( command, stdin=sp.PIPE, stderr=sp.PIPE)
#
# The codec of the output video can be any valid FFMPEG codec but for many
# codecs you will need to provide the bitrate as an additional argument (for
# instance -bitrate 3000k). Now we can write raw frames one after another
# in the file. These will be raw frames, like the ones outputed by FFMPEG in the
# previous section: they should be strings of the form “RGBRGBRGB…” where R,G,B
# are caracters that represent a number between 0 and 255. If our frame is
# represented as a Numpy array, we simply write:
#
# pipe.proc.stdin.write( image_array.tostring() )
# A simple program that continuously polls an Android device
# and screen-grabs screen in PNG format.
# Requires: PyGTK, `adb` in $PATH
from subprocess import Popen, PIPE
import gtk, gobject, threading, time
class MainWindow(gtk.Window):
def __init__(self):
super(MainWindow,self).__init__()
self.img=gtk.Image()
self.add(self.img)
self.stopthread = threading.Event()
threading.Thread(target=self.pull_data).start()
## Thread continously pulls image data over adb from the device.
def pull_data(self):
self.last_time=time.time()
while not self.stopthread.isSet():
# Ideally, your adb tools would support `adb exec-out`
# However, mine does not
# If `adb exec-out` works on your platform, change the following command to:
# proc = Popen(["adb","exec-out","screencap -p"], stdout=PIPE)
# Another potential issue: your device may not support 'stty raw'
# You should try running this command manually in an interactive shell
# to see if it will work.
# `stty` is probably not included on Android devices; however --
# Stericson's BusyBox installer for Android will install this; see
# https://play.google.com/store/apps/details?id=stericson.busybox
#
# As of this writing, I do NOT recommend JRummy's busybox as it seems
# to be buggy.
proc = Popen(["adb","shell","stty raw; screencap -p"], stdout=PIPE)
# Perform blocking I/O
png = proc.communicate()[0]
# Load the PNG image into gdk and obtain a decompressed pixbuf
loader=gtk.gdk.PixbufLoader()
loader.write(png)
loader.close()
pic=loader.get_pixbuf()
self.img.set_from_pixbuf(pic)
# Some helpful framerate statistics
self.current_time=time.time()
print ("{:10.2f} fps\r".format(1.0/(self.current_time - self.last_time))),
self.last_time = self.current_time
# Displays windows if they're not already showing
self.show_all()
def stop(self):
self.stopthread.set()
def main_quit(obj):
global win
win.stop()
gtk.main_quit()
def main():
gtk.gdk.threads_init()
global win
win = MainWindow()
# If we close the main window, this causes the image sucking thread to stop
win.connect("destroy",main_quit)
gtk.main()
# Run our main function if we're in the default scope
if __name__ == "__main__":
main()