connervieira/Predator

[FEATURE] Use ffmpeg for more control over output video file

Closed this issue · 4 comments

Feature Description:
Use ffmpeg as a subprocess to write the video files instead of using OpenCV's writer method.

Usage:
I've implemented a simple ffmpeg class to replace your implementation of cv2.VideoWriter. It's a near drop-in replacement and I'm able to reduce the video file sizes by 50% to 90% relative to your original implementation. Additionally, this also solves the problem of being able to natively playback the videos in a web browser or via Quicktime. When I get a chance, I might create a merge request.

It's worth noting that Predator actually re-encodes videos with FFMPEG at the end of each segment when configured to do so in order to combine audio and video files. Predator used to use FFMPEG to write dashcam videos, but I switched to OpenCV to improve reliability and integration, as well as add new features like dash-cam stamps. FFMPEG recording does indeed result in smaller files, but it's less integrated with Python, and generally less reliable. As such, only completed segments are processed with FFMPEG.

I'm certainly open to adding an FFMPEG back-end as a configurable option, but I'm worried it would introduce a huge amount of complexity and make the project dramatically more complicated to test for reliability.

Here's some things to consider:

  • Both back-ends would need to support the following situations:
    • Only video recording
    • Both video and audio recording to separate files
    • Both video and audio recording to a single combined file
  • The video writing method needs to be able to handle an unexpected fault without losing the current segment:
    • Power loss (the car turning off)
    • Camera disconnects (the camera being damaged in an accident)
    • Removal of the storage media (user removing the drive without turning off the car)
  • The video writing process should be able to "wake up" after a fault has been resolved, and continue writing video without corrupting (for example, a camera is briefly disconnected, then re-connected)

I checked the code. I'm not seeing where you're using FFMPEG to store the segmented video the way I described. You're only using FFMPEG if there's audio and video to merge together. Additionally, OpenCV isn't hardware accelerated for H264. there was a request for it a few years ago, but it never got merged in due to license differences (MIT vs GPL). So, the solution is to use OpenCV to capture and FFMPEG to store using a PIPE. In terms of the reliability, you need to separate out the capture process and original segment writing process, neither of which I see in the code. However, you do use threads for locking/saving segments. Please correct me if I'm wrong on any of the above. Maybe I missed something.

I checked the code. I'm not seeing where you're using FFMPEG to store the segmented video the way I described. You're only using FFMPEG if there's audio and video to merge together.

That's correct. FFMPEG is only used to re-encode video when audio recording is enabled.

In terms of the reliability, you need to separate out the capture process and original segment writing process, neither of which I see in the code.

As of fairly recently, Predator now uses separate threads for capturing video and saving video to disk. The dashcam_output_handler() function runs in a separate thread, and checks if there are new frames that need to be written on a regular interval. The main dashcam capture thread uses the write_frame() function to add frames to the queue. It's worth noting that the write_frame() function does not actually write the frames to disk, but just adds them to the queue to be written.

I've added the ability to set the video file extension and codec in the configuration. I tested it with codec "mp4v" and it seemed to output a valid file. The video played natively on my Linux system, but I haven't tested with QuickTime.

That being said, changing to a non-streamable format means that you'll lose the current segment if the video capture unexpectedly stops.

I'm going to close this issue for now, since I think this resolves the main motivation behind switching to native FFMPEG. If the native FFMPEG implementation still has noticeable benefits, I'll re-open the issue and consider pull requests.