2

I have a Python 3 code that is supposed to record video. Unfortunately, I do not want it in .h264, I need it to convert to .mp4. Using other StackOverflow threads as a template (specifically this one), I thought the easiest way to do this would have been to use subprocess.Popen to insert MP4Box -add filename.h264 filename.mp4 into the terminal and have it do it for me automatically. Unfortunately, the Python script doesn't do anything and I don't get any error messages, so I don't know what's going wrong. The .h264 file appears in the folder I want it to, if I manually put in the command into the terminal the .mp4 appears, but when I just let it run nothing happens. The rest of the script works like a charm. The code is here:

#!/usr/bin/python

from gpiozero import MotionSensor
from gpiozero import Motor
from picamera import PiCamera
import subprocess
import os.path
import shlex
import datetime as dt
from time import sleep

camera = PiCamera()
pir = MotionSensor(4, 1, 100, .6, False)
motor = Motor(3,14) #first number is forwards, second is backwards
startupTime = 1
recordingTime = 1
collectionTime = 3
resetTime = 30



while True:
    sleep(startupTime) #delay a bit so installation can take place

    #wait for motion, then move the motor back and forth
    pir.wait_for_motion() 
    print("Motion Detected")
    #moves motor forward for 3 seconds at 25% speed
    motor.forward(.25)
    print("Strip Extending")
    sleep(3) 
    motor.stop()
    #leaves strip out for given amount of time
    print("Collecting Sample")
    sleep(collectionTime) 
    #moves motor backward for 3 seconds at 50% speed
    motor.backward(.5)
    print("Strip Retracting")
    sleep(3) 
    motor.stop()

    #Prep file for correct saving
    filename = dt.datetime.now().strftime("%Y-%m-%d_%H.%M.%S.h264") #saves file as a date
    save_path= "/home/pi/ANALYSIS"
    completed_video= os.path.join(save_path, filename)

    #Start recording
    camera.start_recording(completed_video) #starts recording and saves it as filename
    print("Camera Recording")
    camera.annotate_text = dt.datetime . now() . strftime("%Y-%m-%d_%H.%M.%S")
    start=dt.datetime.now()

    #Keep recording until time runs out, annotate to make sure we have reference frame
    while (dt.datetime.now() - start).seconds < recordingTime: 
        camera.annotate_text = dt.datetime.now(). strftime("%Y-%m-%d_%H.%M.%S")
        camera.wait_recording(.2)
    camera.stop_recording()

    #Conversion to usable file format
    print("Camera finished recording... Beginning Analysis")
    from subprocess import CalledProcessError
    command = shlex.split("MP4Box -add {} {}.mp4".format(completed_video, os.path.splitext(filename)[0]))
    try:
        output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
    except CalledProcessError as e:
        print('FAIL:\ncmd:{}\noutput:{}'.format(e.cmd, e.output))

    #starts detecting again after given time
    sleep(resetTime)
    print("Ready for next sample")

>Traceback (most recent call last):  
>
    File "/home/pi/Detector.py", line 62, in <module> output = 
      subprocess.check_output(command, stderr=subprocess.STDOUT) 
    File "/usr/lib/python3.4/subprocess.py", line 620, in check_output raise 
      CalledProcessError(retcode, process.args, output=output) 
      subprocess.CalledProcessError: 
        Command '['MP4Box', '-add', '2017-07-11_15.34.49.h264.h264', '2017-07-11_15.34.49.h264.mp4']' 
>
Returned non-zero exit status 1"
stovfl
  • 14,998
  • 7
  • 24
  • 51
NeonCop
  • 75
  • 1
  • 2
  • 12

1 Answers1

1

Comment: 2017-07-11_15.34.49.h264.h264

Your Filepath/Filename is wrong, change to the following:

Note: The .mp4 is saved in to the Current Directory the Subprocess is executed,
the Directory the Python Script is started. This could be different as the .h264 are saved!
Think about to change that also to be a absolute Path.

command = "MP4Box -add {} {}.mp4".format(completed_video, os.path.splitext(filename)[0])
try:
    output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
    print('FAIL:\ncmd:{}\noutput:{}'.format(e.cmd, e.output))

os.remove(path, *, dir_fd=None)

Remove (delete) the file path.


Question: I don't get any error messages, so I don't know what's going wrong.

Try the following:
To also capture standard error in the result, use stderr=subprocess.STDOUT:

command = shlex.split("MP4Box -add {f}.h264 {f}.mp4".format(f=filename))
output = subprocess.check_output(command, stderr=subprocess.STDOUT)
print(output)

I assume you need shell=True as you dont give a Fullpath to MP4Box so a Shell Environment is needed to find MP4Box.

stovfl
  • 14,998
  • 7
  • 24
  • 51
  • It says "Traceback (most recent call last): File "/home/pi/Detector.py", line 62, in output = subprocess.check_output(command, stderr=subprocess.STDOUT) File "/usr/lib/python3.4/subprocess.py", line 620, in check_output raise CalledProcessError(retcode, process.args, output=output) subprocess.CalledProcessError: Command '['MP4Box', '-add', '2017-07-11_15.34.49.h264.h264', '2017-07-11_15.34.49.h264.mp4']' returned non-zero exit status 1" would I add the shell=True after the (f=filename) and after a comma too? – NeonCop Jul 12 '17 at 17:05
  • Ok, I edited it with the most recent error and my updated .py script. I also tried the old code using a different filename so the .h264 didn't repeat, but to no vail. – NeonCop Jul 12 '17 at 20:03
  • It says "No module name 'CalledProcessError'", do I have to import it from another module? – NeonCop Jul 12 '17 at 20:27
  • Oops! Sorry, my bad. I really appreciate your help, you're amazing! I updated with the most recent code and error, I think it's very close now. – NeonCop Jul 12 '17 at 21:00
  • 1
    YES!!!! IT WORKED! Thank you so much, I'd been going crazy for a week. There's an extra parentheses but apart from that your code is gold. – NeonCop Jul 12 '17 at 21:42