I have two videos (A.MOV and B.MOV), that are supposed to be perfectly synced. However, Video A (3708 frames), has 5 more frames than Video B (3703 frames). When I look at the timestamps of these frames, the extra A frames are at the very end of the video. In addition, the last frame in each video is a “padded” frame, with a duration much longer (around 10 times) than that of the other frames.
I need my videos to be perfectly synced, with the same frame number. Since the extra frames are at the end of the video, I want to trim off the extra frames in A, as well as trim the “padded” long frame off of each video.
I currently am running the below MATLAB code to do so,
% Specify the input and output file names
inputVideoFile = 'A.MOV';
intermediateVideoFile = 'A_trim_temp.mp4'; % Temporary file
finalOutputFile = 'A_trim_mat.mp4'; % Final output file
% Create VideoReader object
videoReader = VideoReader(inputVideoFile);
% Get the total number of frames and other properties
numFrames = videoReader.NumFrames;
frameRate = videoReader.FrameRate;
videoHeight = videoReader.Height;
videoWidth = videoReader.Width;
% Create VideoWriter object
videoWriter = VideoWriter(intermediateVideoFile, 'MPEG-4');
videoWriter.FrameRate = frameRate;
open(videoWriter);
% Read and write frames except the last 5
for i = 1:(numFrames - 5)
frame = read(videoReader, i);
writeVideo(videoWriter, frame);
end
% Close the VideoWriter object
close(videoWriter);
% Handle audio extraction and trimming
% This requires an external tool like FFmpeg, as MATLAB does not handle audio directly
% Command to extract audio
audioExtractCommand = sprintf('ffmpeg -i "%s" -q:a 0 -map a audio_original.wav', inputVideoFile);
[status, cmdout] = system(audioExtractCommand);
if status ~= 0
error('Error extracting audio: %s', cmdout);
end
% Command to trim audio (matching the length of the trimmed video)
audioTrimCommand = sprintf('ffmpeg -i audio_original.wav -ss 0 -t %f -c copy audio_trimmed.wav', (numFrames - 5) / frameRate);
[status, cmdout] = system(audioTrimCommand);
if status ~= 0
error('Error trimming audio: %s', cmdout);
end
% Command to merge trimmed audio with the video
audioMergeCommand = sprintf('ffmpeg -i "%s" -i audio_trimmed.wav -c:v copy -c:a aac -strict experimental "%s"', intermediateVideoFile, finalOutputFile);
[status, cmdout] = system(audioMergeCommand);
if status ~= 0
error('Error merging audio and video: %s', cmdout);
end
% Clean up temporary audio files
delete('audio_original.wav');
delete('audio_trimmed.wav');
delete(intermediateVideoFile); % Delete the intermediate file
When I run the above code for Video B, I change
for i = 1:(numFrames - 5)
to
for i = 1:(numFrames - 1)
to remove the padded last frame.
When I run this for both videos, they both return the same frame number (yay!). The timestamps of every frame between A_trim_mat and B_trim_mat match, except for the timestamp of the last frame ( A_trim_mat = 30.8910, B_trim_mat = 30.8890), and perhaps most concerningly, the frame duration between the last two frames of each video is negative (A_trim_mat = -0.0063, B_trim_mat = -0.0083). The duration for all other frames is constant at 0.0083 for both videos.
Any suggestions for how to remedy this are much appreciated. Ideally, I want the timestamps for every frame to match between A and B, and I want the frame duration for each frame to match between A and B.
1