Its a simple class called RaspiVidController which uses threading to not block the calling program but stay alive while the raspivid is running and shut down if you choose to stop it or it times out.
Usage
The class is created by passing 3 parameters:
- filePath - the path of the file where the video is to be saved
- timeout - the time in milliseconds raspivid should run for
- preview - whether raspivid should preview output to the screen
The 3 key methods in the class are:
- start - start raspivid, this immediately returns to the calling program, but raspivid is running in the background
- stopController - stops the controller and raspivid if its running
- isAlive - returns True if raspivid is still running
There is a more complex example in the code below, but a simple example would be:
#create the controller class
vidcontrol = RaspiVidController("/home/pi/test.h264", 10000, False)
#start raspivid
vidcontrol.start()
#DO SOME STUFF
#stop raspivid
vidcontrol.stopController()
vidcontrol = RaspiVidController("/home/pi/test.h264", 10000, False)
#start raspivid
vidcontrol.start()
#DO SOME STUFF
#stop raspivid
vidcontrol.stopController()
Code
import os
import subprocess
import threading
import time
RASPIVIDCMD = ["raspivid"]
TIMETOWAITFORABORT = 0.5
#class for controlling the running and shutting down of raspivid
class RaspiVidController(threading.Thread):
def __init__(self, filePath, timeout, preview, otherOptions=None):
threading.Thread.__init__(self)
#setup the raspivid cmd
self.raspividcmd = RASPIVIDCMD
#add file path, timeout and preview to options
self.raspividcmd.append("-o")
self.raspividcmd.append(filePath)
self.raspividcmd.append("-t")
self.raspividcmd.append(str(timeout))
if preview == False: self.raspividcmd.append("-n")
#if there are other options, add them
if otherOptions != None:
self.raspividcmd = self.raspividcmd + otherOptions
#set state to not running
self.running = False
def run(self):
#run raspivid
raspivid = subprocess.Popen(self.raspividcmd)
#loop until its set to stopped or it stops
self.running = True
while(self.running and raspivid.poll() is None):
time.sleep(TIMETOWAITFORABORT)
self.running = False
#kill raspivid if still running
if raspivid.poll() == True: raspivid.kill()
def stopController(self):
self.running = False
#test program
if __name__ == '__main__':
#create raspivid controller
vidcontrol = RaspiVidController("/home/pi/test.h264", 10000, False, ["-fps", "25"])
try:
print("Starting raspivid controller")
#start up raspivid controller
vidcontrol.start()
#wait for it to finish
while(vidcontrol.isAlive()):
time.sleep(0.5)
#Ctrl C
except KeyboardInterrupt:
print "Cancelled"
#Error
except:
print "Unexpected error:", sys.exc_info()[0]
raise
#if it finishes or Ctrl C, shut it down
finally:
print "Stopping raspivid controller"
#stop the controller
vidcontrol.stopController()
#wait for the tread to finish if it hasn't already
vidcontrol.join()
print "Done"
import subprocess
import threading
import time
RASPIVIDCMD = ["raspivid"]
TIMETOWAITFORABORT = 0.5
#class for controlling the running and shutting down of raspivid
class RaspiVidController(threading.Thread):
def __init__(self, filePath, timeout, preview, otherOptions=None):
threading.Thread.__init__(self)
#setup the raspivid cmd
self.raspividcmd = RASPIVIDCMD
#add file path, timeout and preview to options
self.raspividcmd.append("-o")
self.raspividcmd.append(filePath)
self.raspividcmd.append("-t")
self.raspividcmd.append(str(timeout))
if preview == False: self.raspividcmd.append("-n")
#if there are other options, add them
if otherOptions != None:
self.raspividcmd = self.raspividcmd + otherOptions
#set state to not running
self.running = False
def run(self):
#run raspivid
raspivid = subprocess.Popen(self.raspividcmd)
#loop until its set to stopped or it stops
self.running = True
while(self.running and raspivid.poll() is None):
time.sleep(TIMETOWAITFORABORT)
self.running = False
#kill raspivid if still running
if raspivid.poll() == True: raspivid.kill()
def stopController(self):
self.running = False
#test program
if __name__ == '__main__':
#create raspivid controller
vidcontrol = RaspiVidController("/home/pi/test.h264", 10000, False, ["-fps", "25"])
try:
print("Starting raspivid controller")
#start up raspivid controller
vidcontrol.start()
#wait for it to finish
while(vidcontrol.isAlive()):
time.sleep(0.5)
#Ctrl C
except KeyboardInterrupt:
print "Cancelled"
#Error
except:
print "Unexpected error:", sys.exc_info()[0]
raise
finally:
print "Stopping raspivid controller"
#stop the controller
vidcontrol.stopController()
#wait for the tread to finish if it hasn't already
vidcontrol.join()
print "Done"
Brilliant stuff, Martin. Everyone should use this!
ReplyDeleteTa Mr Horne. I just had to pull something together, more than anything it was driving me mental that something so simple was seemingly so difficult!
DeleteHey this is awesome Martin! I got this to work tonight and can't wait to show my students how they can capture video from their own program!
ReplyDeleteSyntaxError: invalid syntax def __init__(self, filePath, timeout, preview, otherOptions=None):
ReplyDeleteWierd. Wondering whether it is due to non printable characters in the code. Sometimes browsers bring across odd characters when you cut and paste.
DeleteHey we tried you code and its awesome but,
ReplyDeleteI can't do pictures "raspistill" at the same time we are recording the video :(
You know how to take a picture while running a video at same time ?
Hi Albert,
DeleteIm glad it worked for you, however this post is a bit old now and there are better ways of running the raspberry pi camera from python now, check out http://www.stuffaboutcode.com/2014/01/raspberry-pi-camera-python-picamera.html and the picamera module.
Picamera has the ability to take pictures at the same time you are recording video.
error
ReplyDeletepi@raspberrypi ~ $ python RaspiVidController.py
File "RaspiVidController.py", line 44
def stopController(self):
^
IndentationError: unindent does not match any outer indentation level
As per your previous comment, I think this is due to an issue with the indents in the code and more than likely due to cutting and pasting from the web browser
DeleteHi Martin, congratulations for the script, it works fine!
ReplyDeleteI'm working with a project to create a keybinds to start and stop the raspivid in bash but yours works well! I only need one change because i don't know how python works. I need that the script create the videos with different names without user interaction, putting the date&time; a $n,$n+1 number... it's indifferent!
Thanks for all!
Using python-3.2.3
ReplyDeleteRaspberry pi model B+
Debian wheezy 2014-06-04
Traceback (most recent call last):
File "/home/pi/raspivid_proj/test/test.py", line 12, in
class RaspiVidController(threading.Thread):
File "/home/pi/raspivid_proj/test/test.py", line 54, in RaspiVidController
vidcontrol =
RaspiVidController("/home/pi/raspivid_proj/test/test.h264", 10000,
False, ["-fps", "25"])
NameError: name 'RaspiVidController' is not defined
I am not sure why you are getting the error, it could be python 3 related as I wrote this in Python 2.
DeleteHowever if you need to drive the pi camera from python I would recommend you have a look at the picamera module:
http://www.stuffaboutcode.com/2014/01/raspberry-pi-camera-python-picamera.html
This comment has been removed by the author.
DeleteI already done PiCamera b4
DeleteHi, i'm trying to put into the filepath a variable that contains the date&time like "20140824-20:30" to filter the different videos with the date & time parameter. How can i put it into your code? Thanks in advance
ReplyDeleteIf I was you, I would have a look at the python module picamera. Its a much easier method of using the raspberry pi camera from python https://picamera.readthedocs.org http://www.stuffaboutcode.com/2014/01/raspberry-pi-camera-python-picamera.html
DeleteMartin thanks for the code. I was able to see a full screen preview by adding an addition line:
ReplyDeleteself.raspividcmd.append("-p"). But is there a way to change the preview window size such as in raspistill (-p 100,100,300,200).?
Thanks,
Danny
Hi Danny,
DeleteThere probably is a way of making it work, however I would recommend that you have a look at the python picamera module https://picamera.readthedocs.org/en/release-1.10/ its a much better and easy way of interacting with the pi camera with python.
Hi and thanks for the great module!
ReplyDeleteI am trying to run the example as follows, and then convert it to an MP4 with mp4box. I have modified the class to use only the filepath and otherOptions, because I want to start and stop recording with a GPIO button.
the constructor now looks like this:
class RaspiVidController(threading.Thread):
def __init__(self, filePath, otherOptions=None):
threading.Thread.__init__(self)
#setup the raspivid cmd
self.raspividcmd = RASPIVIDCMD
#add file path, timeout and preview to options
self.raspividcmd.append("-o")
self.raspividcmd.append(filePath)
I am instantiating the controller like this:
vidcontrol = RaspiVidController("/home/pi/newvid.h264,", ["-t", "5000","-rf", "rgb" , "-pf", "high", "-drc", "low", "-sa", "-50", "-vs", "-br", "40", "-fps", "30", "-b", "12000000" ])
and trying to make the file with
vidcontrol.start()
and
vidcontrol.stop()
The problem is that it does not create newvid.h264 anywhere. Any ideas? I also had the same result with your code and the simple example too.
Any help would be greatly appreciated!