Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HOW-TO] change FPS using picamera 2 #1128

Open
NadiaColodro opened this issue Oct 7, 2024 · 3 comments
Open

[HOW-TO] change FPS using picamera 2 #1128

NadiaColodro opened this issue Oct 7, 2024 · 3 comments

Comments

@NadiaColodro
Copy link

Hi! I’m trying to change the FPS when i record, but the video duration becomes inaccurate when I convert it to MP4 and it lasts much less or accelerates the video. Do you have any suggestions on how to fix this? Here is my code:

#This script records a video for the specified time, converts the video to mp4 format, then uploads the video to a specified cloud location. It also creates a log file documenting each step in the script.
Variables - update as needed

this_pi = 'raspi0'  # Enter identifying info for recording here (e.g. subject ID). Appears in file name and annotation text
brightness = 60  # integer between 1-100. 50 is usually a good place to start
contrast = 700    # integer between 1-100. 50 is usually a good place to start
recording_length = 1200  # number of secs. 1 hour = 3600 secs, 5 minutes = 300 secs
rclone_config = 'lowell_lab:Recordings/'

from picamera2 import Picamera2
from picamera2.encoders import H264Encoder
from picamera2.outputs import FileOutput
from time import sleep
import os
import subprocess
from datetime import datetime
import logging
from libcamera import controls

today = datetime.now()
d1 = today.strftime("%d_%m_%Y")
d2 = today.strftime("%d_%m_%Y__%H_%M_%S")
d3 = today.strftime("%d_%m_%Y__%H_%M")

name = f"{this_pi}_{d3}"
file = f"{name}.h264"
path = f"/home/nadia/Videos/{file}"
file2 = f"{name}.mp4"
path2 = f"/home/nadia/Videos/{file2}"

log_file = f"/home/nadia/Documents/Logs/{name}.txt"
logging.basicConfig(filename=log_file, level=logging.INFO, format='%(asctime)s:%(levelname)s:%(message)s')
logging.info(f"{this_pi} {d1}")

print("Starting recording")
logging.info("Starting recording")

# Initialize Picamera2
camera = Picamera2(0)
video_config = camera.create_video_configuration(main={"size": (1920, 1080), "format": "YUV420"})
camera.video_configuration.controls.FrameRate= 25.0
camera.configure(video_config)

# Set autofocus control
camera.set_controls({"AfMode": controls.AfModeEnum.Continuous})

try:
    camera.start_preview()
    # Start recording
    output = FileOutput(path)
    encoder = H264Encoder(bitrate=2000000)  # Adjust bitrate for quality
    camera.start_recording(encoder, output)
    sleep(recording_length)  # Record for the specified duration
    camera.stop_recording()
    camera.stop_preview()
    print("Finished recording")

except Exception as e:
    logging.exception('Recording error found')
    new_log_file = f"/home/nadia/Documents/Logs/FAILED_recording_{name}.txt"
    os.rename(log_file, new_log_file)
    raise

print("Beginning conversion to MP4")
logging.info("Beginning conversion to MP4")

# Convert file to MP4 format. Requires command line subprocess
from subprocess import CalledProcessError
command = f"ffmpeg -i {path} -c:v copy {path2}"
try:
    output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
    logging.info('MP4 conversion FAIL:\ncmd:{}\noutput:{}'.format(e.cmd, e.output))
    new_log_file = f"/home/nadia/Documents/Logs/FAILED_mp4_conversion_{name}.txt"
    os.rename(log_file, new_log_file)
    raise

print("Conversion finished... Starting MP4 upload")
logging.info("Conversion finished... Starting MP4 upload")

# Upload MP4 to cloud
upload = f"rclone move {path2} {rclone_config} --contimeout=40m"
os.system(upload)

print("Removing H264 file")
logging.info("Removing H264 file")

try:
    os.remove(path)
    print("H264 video moved to trash")
    logging.info("Videos moved to trash")
except Exception as e:
    logging.exception("H264 removal error")
    new_log_file = f"/home/nadia/Documents/Logs/FAILED_delete_{name}.txt"
    os.rename(log_file, new_log_file)
    raise

# Print remaining files in Video directory
vids_list = os.listdir('/home/nadia/Videos/')
vids = '\n'.join(vids_list)
print("Remaining videos:" + vids)
logging.info('Remaining videos:' + vids)
`
@NadiaColodro
Copy link
Author

I'm using a raspberry pi 5 and camera module 3!

@davidplowman
Copy link
Collaborator

The problem is likely to be that H.264 output files don't contain timestamps, so when you convert it to mp4 it picks some unspecified framerate.

Usually, when you convert to mp4, I would expect the tool to accept some kind of "framerate" parameter, so that you can adjust this to match the real framerate.

Alternatively, when you start recording, there's a pts parameter which you can use to write a file containing timestamps. Some tools (maybe makemkv?) may accept this as input.

Finally, you could use the FfmpegOutput class instead of FileOutput. This should get the timestamps approximately right, though note that Ffmpeg will resample them and so they will exhibit a fair degree of jitter. But it should be "close".

@NadiaColodro
Copy link
Author

Thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants