Clear Filters
Clear Filters

What do I do to make a function step that writes all frames, not just the last frame?

2 views (last 30 days)
readObject = vision.VideoFileReader('video_001.avi', 'AudioOutputPort',true);
%% Video File Writer Objekt erstellen
writeObject = vision.VideoFileWriter('video17.avi', 'FileFormat','avi', 'AudioInputPort',true, 'FrameRate',readObject.info.VideoFrameRate, 'Quality',90);
writeObject.AudioInputPort=true;
%% Video Frame aus .avi-Objekt holen und in .mp4-Objekt schreiben
while ~isDone(readObject)
[frame, audio] = step(readObject); %[frame, audio] = avi();
end
step(writeObject,frame, audio); %mp4(frame, audio);
release(readObject);
release(writeObject);
I want to read the audio and frames by using vision.VideoFileReader; then do some processing on the frames, then write frames and audio in a file, but I do not want to use the 'while' used during reading

Accepted Answer

Walter Roberson
Walter Roberson on 12 Mar 2020
It is not possible to achieve your goals. You have chosen to use vision.VideoFileReader() which does not have a "read all frames" function, only a "read the next frame" function. You must use a loop to read all of the frames.
Well, we could cheat on the spirit of the law but adhere to the letter of the law by recording the
while ~isDone(readObject)
as
for iteration = 1 : inf
if isDone(readObject); break; end
something
end
This uses a for loop instead of a while loop.
It would be quite legitimate to ask whether we could find out how many frames there were before doing the reading, and then use a for loop over that count. If we could then we would be able to pre-allocate storage for all the frames and audio together, which would be beneficial.
The answer to that question is that it turns out that the frame counts you get in video files are typically not reliable, especially for variable-frame-rate files. The frame count tends to be based upon multiplying the time the video is supposed to last, by the frame rate -- but you can't do that accurately if the frame rate is variable. It also turns out that it is common to use nominal frame rates instead of exact frame rates, such as using 30 fps when the actual rate is 29.95 fps. Frame rates are not integers either, so you tend to get rounding errors on the exact count.
So unfortunately the only reliable way to find out the exact number of rames ahead of time is to read through the file and count them.
That said, there is still quite a bit of efficiency gain to be had by estimating the number of frames. Even deliberately over-estimate, and allocate more than you need, and then use a while loop structure to loop for the actual end of frames, keeping count as you read them in. Afterwards, trim back from the (overestimated) memory to the actual count: this only involves resizing the data structure once, instead of having to re-size every time you add another frame.
  18 Comments
Walter Roberson
Walter Roberson on 21 Mar 2020
The frames matrix is a 4D matrix. You cannot use the * operator with a 4D matrix, only with scalars or vectors or 2D arrays.
The number of rows and columns of the frames array are not equal to each other. If you were to ask that each pane of frames were to be handled independently, then you could potentially define your question in terms of a number of operations on 2D arrays. However, when you have two 2D arrays of the same size, A and B, the only time that A*B is valid is if size(A,2) == size(B,1) and that condition can never be met with two arrays the same size when the number of rows is different from the number of columns.
If would suggest that you reconsider using the * operator. It would make more sense to do something like,
resulr = frames .* randi(FC, size(frames));

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!