2

I want to make a timelapse with my Pi, but rather than storing thousands of images on my small SD card and then spend hours mencoder'ing the result, I'd like to pipe the raspistill -tl output (if possible) into mencoder, and get the resulting compressed video when I stop the process.

Since I plan to take 1 picture every 5s, I figure there's plenty of time to append that image to the mencoder video between shots.

Is is possible?

I tried a simple script but have an error:

$ raspistill -a 12 -tl 1000 -t 10800000 -o - | mencoder - -nosound -ovc lavc -lavcopts vcodec=mpeg4:aspect=16/9:vbitrate=8000000 -vf scale=1920:1080 -o timelapse.avi -mf type=jpeg:fps=30
MEncoder SVN-r37379 (C) 2000-2015 MPlayer Team
Reading from stdin...
success: format: 0  data: 0x0 - 0x0
libavformat version 56.25.101 (internal)
Cannot seek backward in linear streams!
Seek failed
Cannot seek backward in linear streams!
Seek failed
Cannot seek backward in linear streams!
Seek failed

I suppose a list of JPG is not exactly what mencoder gets from the input. Any guru here to help me?

edit

With a separate command invocation:

raspistill -a 12 -tl 1000 -t 10000 -o - > test.raw # takes 10 images across 10 s
mencoder test.raw -nosound -ovc lavc -lavcopts vcodec=mpeg4:aspect=16/9:vbitrate=8000000 -vf scale=1920:1080 -o timelapse.avi -mf type=jpeg:fps=30

This produces a valid video, so there's something in the pipe that doesn't work correctly.

  • I suppose a list of JPG is not exactly what mencoder gets from the input. I suppose you're right. Try piping it to a file to see what you're getting (e.g. raspistill -a 12 -tl 1000 -t 10800000 -o - > output. Then open the output file and see what's there. I don't think it will solve anything, but it may help you figure out what's happening. If piping output doesn't work you could try having it save to the SD, feed the image to mencoder, and delete it. Sorry I'm not a guru! – Nateowami Jan 16 '16 at 13:42
  • FWIW it works with this, I can have that file sent to mencoder and it can encode the timelapse. So it should work with a pipe but it doesn't. – Gui13 Jan 16 '16 at 14:05
  • If mencoder is expecting the input to be seekable, then the file will be but the pipe obviously won't. If that's the issue then in the second case, trying cat test.raw | mencoder - -nosound ... -o timelapse.avi should also fail. However, if that's the case I'm not sure there's anything you can do about it. – Dave Jones Jan 17 '16 at 19:23
  • I can understand that, but then would it be possible to have some sort of "rolling buffer" where raspistill can deposit the last, say, 10 or 50 images and let mencoder seek in there? I'd really like to not screw my SD card taking so many pictures, plus having the ability to have a "rolling" timelapse that could last for months. – Gui13 Jan 17 '16 at 22:20
  • @Gui13 On a hunch try adding -cache 1024 as an argument to mencoder (or perhaps a larger number). This is supposed to solve the same error with mplayer. mencoder also accepts the cache option and your comment about the buffer made me think this just might work. Sorry my Pi is giving me trouble otherwise I'd try it myself first. – Nateowami Jan 18 '16 at 2:18
1

I was trying to do the exact same thing. After fiddling around with terminal piping and getting rather mixed results (incomplete files, dropped frames, large filesize, etc.), I found that the Python picamera module (preloaded on Raspbian) can give excellent H.264 timelapse videos easily.

For the Camera module v1, PiCamera allows setting the video framerate as low as one frame per 6 seconds. For the Camera module v2, the framerate can go down to one frame per 10 seconds. These should cover most use cases.

The bonus is that all processing is done on the GPU, so this requires almost no CPU time.

Example:

from picamera import PiCamera
from fractions import Fraction
camera = PiCamera()
try:
        camera.resolution = (1920, 1080)  # 1080p is the max resolution of the H.264 encoder
        camera.framerate = Fraction(1, 3) # One frame every 3 seconds
        camera.start_recording('output.mp4', format='h264', quality=23)
        camera.wait_recording(300)        # Time of recording, in seconds
        camera.stop_recording()
finally:
        camera.close()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.