Search code examples
pythonterminalraspberry-picommandraspbian

(python 3) Auto-Conversion from .h264 to .mp4


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"

Solution

  • 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.