【问题标题】:Matlab: Why can't I create an mp4 file using VideoWriter?Matlab:为什么我不能使用 VideoWriter 创建一个 mp4 文件?
【发布时间】:2019-12-29 17:27:52
【问题描述】:

我想删除视频的背景。之后我想把它放到另一个视频中,然后将它保存为一个新的 mp4 文件。我使用的是 Windows 10,但遇到以下问题,即在运行代码后无法创建新的 mp4 文件。

想法: 我有一辆车,后面有绿屏。我想把这辆车剪下来,放在街头视频的前面。 结果应该是一辆汽车在街上行驶(视频)。

来自 myScript 的代码:

clear
close all
v = VideoReader(fullfile('videos', 'carWithGreenscreen.mp4'));
s = VideoReader(fullfile('videos','street.mp4'));

video=zeros(v.Height,v.Width,3,floor(v.Duration/(1/v.FrameRate))-2,'uint8');
t=1;
car = 0.6 ;
values=[0;1;0];
while hasFrame(v)
    Img = im2double(readFrame(v));
    mask = sqrt((values(1)-Img(:, :, 1)).^2+(values(2)-Img(:, :, 2)).^2+(values(3)-Img(:, :, 3)).^2)<car;
    video(:,:,:,t) = imoverlay(im2uint8(Img),mask,[0 0 0]);
    imshow(video(:,:,:,t));
    t=t+1;
end

videoOut = VideoWriter('result.mp4','MPEG-4'); %here I want to create a video%
videoOut.FrameRate=v.FrameRate;
open(videoOut);
moveX=0;
for t=1:1:size(video,4)
    im = video(:,:,:,t);
    mask = im(:,:,1)+im(:,:,2)+im(:,:,3)==0;
    frame=imoverlay(readFrame(s),~mask,[0 0 0]);
    frame=frame+im;
    writeVideo(videoOut,frame);
    imshow(frame);
end
close(videoOut);

运行此代码后出现以下错误:

Error using myScript (line 27)
No more frames available to read from file.
line 27: frame=imoverlay(readFrame(s),~mask,[0 0 0]);

但最后它并没有创建一个 mp4 文件......我已经用 avi 尝试过,但我只创建了一个 0KB 的空 .avi 文件......

【问题讨论】:

  • 我已将 for 循环更改为 while hasFrame(s),现在出现此错误:>> myScript 警告:没有视频帧写入此文件。该文件可能无效。 > 在 VideoWriter/close 中(第 282 行)在 myScript 中(第 32 行)
  • 第 32 行:关闭(videoOut);
  • 两个视频的帧数相同 25 并且两个视频都是 10 秒长。
  • 我至少应该制作一个视频......

标签: matlab video output frames


【解决方案1】:

我设法重现了这个问题,它看起来像一个codec 问题。

我下载了FFmpeg命令行工具,并生成了示例(合成)视频:

对于carWithGreenscreen.mp4,我选择了libxvid编解码器:

ffmpeg -r 2.5 -f lavfi -i testsrc=rate=1:size=320x256 -t 10 -c:v libxvid videos/carWithGreenscreen.mp4

对于street.mp4,我选择了libx264编解码器:

ffmpeg -r 2.5 -f lavfi -i mandelbrot=rate=1:size=320x256 -t 10 -c:v libx264 videos/street.mp4

在 Windows 10 的 MATLAB R2019a 中执行脚本时,我收到相同的错误消息:

使用 myScript 时出错(第 27 行)
没有更多的帧可用于从文件中读取。

当我为street.mp4 选择libxvid 时,脚本正在运行。

显然,MATLAB 对 h264 编解码器的支持是有限的。
根据文档,支持 h264 编解码器,但由于某种原因它不起作用,我找不到解决方案。


这里有一个变通的解决方案:

  • 使用 FFmpegstreet.mp4 转换为未压缩的 AVI。
    首选未压缩的 AVI 格式,因为没有转码(不会丢失数据)。
    (下载静态链接的 FFmpeg 最新稳定版)。

您可以在 MATLAB 中执行 FFmpeg 来执行转换(在将 ffmpeg 可执行文件与您的脚本放在同一文件夹中之后):

% Convert street.mp4 to street.avi (create uncompressed AVI video file)
[status, cmdout] = system(['ffmpeg -y -i ', fullfile('videos','street.mp4'), ' -c:v rawvideo -pix_fmt bgr24 ', fullfile('videos','street.avi')]);

if (status ~= 0)
    display(cmdout); % Displat cmdout in case of an error.
end

%Open street.avi instead of street.mp4
s = VideoReader(fullfile('videos','street.avi'));

以下是修改后的完整代码:

clear
close all
v = VideoReader(fullfile('videos', 'carWithGreenscreen.mp4'));

%s = VideoReader(fullfile('videos','street.mp4'));

% Convert street.mp4 to street.avi (create uncompressed AVI video file)
[status, cmdout] = system(['ffmpeg -y -i ', fullfile('videos','street.mp4'), ' -c:v rawvideo -pix_fmt bgr24 ', fullfile('videos','street.avi')]);

if (status ~= 0)
    display(cmdout); % Displat cmdout in case of an error.
end

%Open street.avi instead of street.mp4
s = VideoReader(fullfile('videos','street.avi'));

video=zeros(v.Height,v.Width,3,floor(v.Duration/(1/v.FrameRate))-2,'uint8');
t=1;
car = 0.6 ;
values=[0;1;0];
while hasFrame(v)
    Img = im2double(readFrame(v));
    mask = sqrt((values(1)-Img(:, :, 1)).^2+(values(2)-Img(:, :, 2)).^2+(values(3)-Img(:, :, 3)).^2)<car;
    video(:,:,:,t) = imoverlay(im2uint8(Img),mask,[0 0 0]);
    imshow(video(:,:,:,t));
    t=t+1;
end

videoOut = VideoWriter('result.mp4','MPEG-4'); %here I want to create a video%
videoOut.FrameRate=v.FrameRate;
open(videoOut);
moveX=0;
for t=1:1:size(video,4)
    im = video(:,:,:,t);
    mask = im(:,:,1)+im(:,:,2)+im(:,:,3)==0;
    frame=imoverlay(readFrame(s),~mask,[0 0 0]);
    frame=frame+im;
    writeVideo(videoOut,frame);
    imshow(frame);
end
close(videoOut);

%Delete VideoReader objects (force closing the files).
v.delete();
s.delete();

最后一帧样本(两个合成模式的叠加):

【讨论】:

  • 非常感谢它现在适用于 .avi 文件:)。我认为 Windows 10 的 mp4 编解码器存在一些问题,因为其他使用 MacOS 的学生在创建结果文件时没有这个问题。你拯救了我的一天 :)
  • 请注意:mp4 不是编解码器,mp4 是一个“容器”,可能包含视频、音频和字幕流(以及更多)。视频流使用特定的编解码器进行编码。 mp4 支持许多视频和音频编解码器选项。如果您需要查看编解码器信息,我建议使用mediainfo 工具。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多