各位同学好,各位知乎的小伙伴们大家好。今天,我要给大家分享的内容是:“如何在Matlab GUI中播放带声音的视频?”

这个问题有点奇怪,什么叫做带声音的视频?视频一般不都是带声音的吗?

没错,一般视频都是带声音的。而且,Matlab是擅长处理视频的,网上找到的教程也确实能够把视频文件读取,处理成一帧一帧的,然后播放出来。但是,问题出在很少有教程把“声音”问题处理好,视频处理成图像逐帧播放却没有声音,让人非常着急。

“没有声音,再好的戏也出不来!”

这个教程会完整地教会大家怎么把视频文件处理好,既能够播放图像,同时也能够播放声音。

我们把整个教程分为六个部分:

(1)读取视频文件(不带声音);

(2)读取视频文件的声音部分;

(3)搭建播放视频的Matlab GUI框架(表面);

(4)实现播放视频的操作;

(5)实现播放声音的操作;

(6)利用跟随变量在一个按钮上实现播放和暂停。

(1)读取视频文件(不带声音)

读取视频文件的标准操作需要用到VideoReader,我们看下面这句代码:

mp4FileName = 'Friends.mp4';
mVideo = VideoReader(mp4FileName);

读取后,mVideo这个结构体包含如下变量:

Duration - 视频的总时长(秒)

FrameRate - 视频帧速(帧/秒)

NumberOfFrames - 视频的总帧数

Height - 视频帧的高度

Width - 视频帧的宽度

BitsPerPixel - 视频帧每个像素的数据长度(比特)

VideoFormat - 视频的类型, 如 'RGB24'.

Tag - 视频对象的标识符,默认为空字符串''

Type - 视频对象的类名,默认为'VideoReader'.

UserData - 用户定义的数据,指定为任意数据类型的值,一般默认为“[ ]”

NumberOfFrames - 视频的总帧数。

宽和高信息对于确定窗口和坐标轴控件的属性是有用的,所以一般我们会有意识地把这个变量提取出来:

vWidth = mVideo.Width;
vHeight = mVideo.Height;
vFrameRate = mVideo.Framerate;

我们还提取了视频帧速这个变量,它可以用来决定播放速度的。

(2)读取视频文件的声音部分

读取视频文件的声音部分需要用到mmread这个工具包,代码示例如下:

[mVar01 mAudio] = mmread(mp4FileName);

这里的问题是mmread不像VideoReader,是Matlab自带的函数,它需要专门做一次“设置路径”的操作。

这个“设置路径”的按钮就在中间的位置,“布局”按钮的右侧,“预设”按钮的下方。点击这个按钮,会弹出一个对话框:

我们采用“添加并包含子文件夹”的方式添加了当前工作目录下面的mmread文件夹,至此,我们就可以利用这个工具包中的mmread函数来读取.mp4文件的音频部分的信息。

(3)搭建播放视频的Matlab GUI框架(表面)

function y = matlabgui_mp4Player(~)% prepare
mp4FileName = 'Friends.mp4';
mVideo = VideoReader(mp4FileName);% get the info of width and height
vWidth = mVideo.Width * 2;
vHeight = mVideo.Height * 2;% create a figure
hFigure = figure(1);
set(hFigure, 'position',[100 50 vWidth vHeight+100]);% create an axes
hAxes = axes('parent',hFigure);
set(hAxes, 'units','pixels', 'position',[1 101 vWidth vHeight]);% create a image object, and set its 'parent' property
hImage = image(readFrame(mVideo), 'parent',hAxes);
%
% % create a pushbutton
hPushbutton = uicontrol(hFigure, 'Style','pushbutton', 'String','Play', 'position',[1 1 vWidth 100]);  y = hFigure;
end

细心的朋友应该注意到了,我把从视频中获取的高度和宽度都乘以了一个系数2,与此同时,我在设置hFigure的时候,在视频高度的基础上增加了一个100,并且坐标轴的高度也上提了100个像素。前者这么操作是因为我们使用的Friends.mp4文件是压缩过的,如果按照正常的比列进行播放的话会非常小,只有220 x 176。后者操作是为了给hPushbutton这个按钮控件留出空间。我们看下最后的布局效果:

大家对看到的黑色有可能产生两种理解,一种是这个黑色是控件默认的颜色,另外一种是这个黑色是读取的视频的第一帧image到坐标轴上的效果。后面这种猜测才是对的!这里关键是对readframe函数的理解。为了更准确地理解这个函数,我们试着用一个循环,假装运行readframe函数200次试试:

这就验证了第二种理解是正确的。同时,我们大概能够理解,readframe这个函数,运行一次,某个类似指针的用来标记frame的变量会跳到下一帧。有了这个理解,我们就可以人为地设置一个Timer控件,按照视频自身的每秒帧数的节奏播放画面,就可以达到播放视频的效果。

(4)实现播放视频的操作

因为运行一次readframe,指针就会跳到下一帧,这个就为我们播放视频提供了便利。配合Timer控件的使用,我们可以做到收放自如。先定义一个Timer:

% timer
global t;
timePeriod = round(1/vFrameRate,3);
t = timer('timerFcn', {@timerFcn, mVideo, hImage}, 'ExecutionMode','Fixedrate', 'Period',timePeriod);

然后要专门写一个它的回调函数timerFcn:

% function --> timerFcnfunction timerFcn(obj, ~, v, hIM)if hasFrame(v)set(hIM,'cdata',readFrame(v));elsestop(obj);endend

在定义Timer控件的时候,可以利用元胞格式{},往timerFcn函数中传入视频变量(mVideo是实参,v是形参),还有图层句柄(hImage是实参,hIM是形参)。呈现图片用的是set函数,set(hIM,'cdata',readFrame(v))修改hImage句柄的cdata参数就可以把读取的那一帧图像呈现在图层上。

这里用了一个if判断语句,如果还有帧的话,就执行呈现图片的操作;如果没有的话(hasframe函数是用来确定视频变量中的帧是否可供读取),就把obj给停止了。这里的obj就是这个函数的源对象,也就是Timer控件t。因为t是全局变量,所以obj也可以写成stop(t)效果应该是一样的。

(5)实现播放声音的操作

之前通过mmread读取了mp4文件:

[mVar01 mAudio] = mmread(mp4FileName);

但是,这样是不能播放声音的,还需要打造一个mp3player对象:

global mp3player;
mp3player = audioplayer(mAudio.data, mAudio.rate, mAudio.bits);

有了这个对象之后,不管是播放play,终止stop,暂停pause,还是恢复播放resume,都可以直接运用在这个对象上。比如,

play(mp3player);

就可以开始播放当前的mp3,也就是从视频中读取的音频部分。

(6)利用跟随变量在一个按钮上实现播放和暂停

作为标题,这么描述有点过于简单了,实际上整个播放包括一开始的启动play,暂停pause,恢复resume和退出后的停止stop。我们会引入一个全局变量叫做mState,它可以标记当前的状态是初始状态0,播放状态2,抑或是暂停状态1,直接粘贴完整版代码(想象一下这时候是有BGM的):

function y = matlabgui_mp4Player(~)% prepare
mp4FileName = 'Friends.mp4';% read the video and audio via VideoReader and mmread
mVideo = VideoReader(mp4FileName);
[mVar01 mAudio] = mmread(mp4FileName);% get the info. from mVideo
vWidth = mVideo.width * 2;
vHeight = mVideo.height * 2;
vFrames = mVideo.NumberOfFrames;
vFrameRate = mVideo.Framerate;% prepare mp3player obj
global mp3player;
mp3player = audioplayer(mAudio.data, mAudio.rate, mAudio.bits);% create a figure
hFigure = figure(1);
set(hFigure, 'position',[100 50 vWidth vHeight + 100]);
%
% create an axes
hAxes = axes('parent',hFigure);
set(hAxes, 'units','pixels', 'position',[1 101 vWidth vHeight]);% create a image object, and set its 'parent' property
hImage = image(readFrame(mVideo), 'parent',hAxes);
%
% % create a pushbutton
hPushbutton = uicontrol(hFigure, 'Style','pushbutton', 'String','Play', 'position',[1 1 vWidth 100]);   % , % timer
global t;
timePeriod = round(1/vFrameRate,3);
t = timer('timerFcn', {@timerFcn, mVideo, hImage}, 'ExecutionMode','Fixedrate', 'Period',timePeriod);%
global mState;
mState = 0; % 0 == original vs. 1 == pause vs. 2 == play% assign y
y = hFigure;% % Binding  Mechanism
set(hPushbutton,'Callback',@hPushbutton_CallbackFcn);
set(hFigure, 'DeleteFcn',@hFigure_DeleteFcn);
%
% function --> hPushbutton_CallbackFcnfunction hPushbutton_CallbackFcn(obj, event, hs)if mState == 0start(t);play(mp3player);set(obj, 'String','Pause');mState = 2;elseif mState == 1start(t);resume(mp3player);set(obj, 'String','Pause');mState = 2;elsestop(t);pause(mp3player);set(obj, 'String','Resume');mState = 1;endendend% function --> timerFcnfunction timerFcn(obj, ~, v, hIM)if hasFrame(v)set(hIM,'cdata',readFrame(v))elsestop(obj);endend%
% % function --> hFigure_DeleteFcnfunction hFigure_DeleteFcn(obj, event, hs)stop(t); delete(t); stop(mp3player);endend

补充一些细节:

(1)一旦我们设定了一个Timer控件,就要记得在退出窗口的时候,把这个timer对象停止并删除。

(2)退出窗口的时候,同样要记得停止mp3player对象,否则窗口关闭之后,声音会一直播放感觉很奇怪。

(3)mState实际上是3种状态,一开始为0,点击按钮就开始播放;播放时为2,点击按钮会出现暂停;进入暂停状态之后为1,点击按钮继续播放。

(4)image和imshow都可以用来把图像矩阵显示在坐标轴上,这里用了image是因为两个原因。第一,它在性能方面是优于imshow的,在这种连续播放图像帧的操作中,肯定会选择性能更优的image函数;第二,是因为image有一个自适应的缩放功能,hAxes在定义时用的是图像矩阵的两倍宽和高,image自动把图像矩阵放大了呈现在坐标轴上。

(5)VideoReader类中的readframe这个操作在2018b版本是会运行报错的,原因是我的这个版本的代码中有一句是这么写的:

vFrames = mVideo.NumberOfFrames;

然后就会报错:

错误使用 VideoReader/readFrame (line 99)
不能在查询 NUMBEROFFRAMES 属性或使用 READ 方法后调用
'READFRAME' 方法。

这里有两个建议,一个是采用2019b及以上版本,另外一个是注释掉“vFrames = mVideo.NumberOfFrames;”的语句即可。

(6)还有一个很小的细节,就是我们的mp4文件名不能带中文,不然会报错。

到这里,整个教程就写完了。国庆节&中秋节快乐♥

感谢李昌锦和杨轩两位同学的卓越贡献,mmread工具包就是他们找到的。多亏了他们,要不然也不太可能有这么完整的一个教程,♥谢谢谢谢♥

.

lsdyna如何设置set中的node_list_如何在Matlab GUI中播放带声音的视频?相关推荐

  1. matlab中med是什么意思,matlab GUI中使用中值滤波medfilt2 的问题

    本帖最后由 NorthLion 于 2015-8-31 09:55 编辑 问题已经解决了,谢谢! matlab GUI读取一张图片.在test3_axes1显示,对这张图片进行中值滤波并在test3_ ...

  2. matlab静态文本框显示,如何在Matlab GUI中利用静态文本框显示程序的结果

    www.mh456.com防采集. 调用2113pushbutton的回调函数,再用set让结构在5261文本框中显示.给4102一个简单的例1653子:内pushbutton的回调函数(实现两容个数 ...

  3. matlab yalmip安装教程,如何在matlab路径中安装yalmip Matlab R2014a添加yalmip图文教程

    yalmip是什么?可以说,yalmip是一位"集大成者",它不仅自己包含基本的线性规划求解算法,比如linprog(线性规划).bintprog(二值线性规划).bnb(分支界定 ...

  4. Matlab GUI中的hObjecthandles

    Matlab GUI中的hObject与handles ①如果把figure对象当做一个大缸,把其它的对象如axes,button等当做这个大缸里的小缸,那么handles就相当于这个大缸的句柄,可以 ...

  5. 8. 修改matlab GUI中fig和m文件名修改流程及注意事项

    资料来源: 修改matlab GUI中fig和m文件名修改流程及注意事项 - CSDN博客 https://blog.csdn.net/xingkongfenqi/article/details/46 ...

  6. 计算机中如何设置电源计划为节能,如何在Windows 10中创建电源选项快捷图标,快速设置笔记本电脑的节能模式...

    原标题:如何在Windows 10中创建电源选项快捷图标,快速设置笔记本电脑的节能模式 在笔记本电脑上「电源计划」的设定,除了火力全开的高性能运作外,也可以设定成省电模式来节省电量,不过一般都需要到「 ...

  7. m 文件 dll matlab 中调用_如何在matlab中调用python程序

    现在python很火,很多代码都是python写的,如果你和我一样,习惯了使用matlab,还想在matlab中调用Python的代码,应该怎么办呢?其中一条思路:首先在matlab中调用系统脚本命令 ...

  8. 在html表格中进行计算,如何在word表格中实现计算功能?超级实用,值得细细品味...

    常听同事们说:word就是文字处理,excel就是制表计算.乍一听,也没什么不妥啊,但细细一想,这是对word很大的伤害. 今天得改改这种看法了,其实,word表格也有计算功能,例如:在财务报表.工资 ...

  9. 在matlab gui中播放视频的方法

    这个项目仅仅作为gui播放视频的验证 视频文件前处理:讲要播放的视频用视频剪辑软件调整到合适的时长,注意这个视频的时长不是在gui界面上的播放时长,因为imshow函数会有可观的运行时间,导致在gui ...

最新文章

  1. 前端性能优化 —— 项目瘦身
  2. CentOS 6.5安装python3.3.4
  3. 71道Android开发面试题
  4. 指尖上的电商---(4).net开发solr
  5. Beautiful Lyrics
  6. 关于反射的完整 练习
  7. linux实现乘法函数,linux命令行计算器
  8. android studio简易记账本,Android记账本
  9. 与时间相关的java源码_Java 调整日期和时间
  10. WEB安全基础-点击劫持漏洞基础
  11. 信息学奥赛一本通(1069:乘方计算)
  12. Linux中的configure、pkg-config、pkg_config_path
  13. latex 编译缺少STXingkai字体
  14. 用计算机打字教案,使用打字软件练指法教案
  15. javaWeb文档预览之office转pdf(附详细代码)
  16. php qq邮箱验证码不显示图片,qq邮箱邮件图片不显示怎么解决-解决qq邮箱邮件图片不显示的方法 - 河东软件园...
  17. ClickME 隐私策略
  18. Win11如何清除最近打开过的文件记录?
  19. 音频电解电容应用方法及经验
  20. M1卡修改各区块控制位值和数据

热门文章

  1. P7960 [NOIP2021] 报数 题解
  2. python练习册 from github
  3. requests模块 简单使用
  4. 《纳什均衡与博弈论》
  5. 结合协同过滤和个性化AGENT的增强推荐
  6. JAVA Web项目开发SSM框架搭建(第一天)
  7. c语言库函数strtoul
  8. Unity Camera摄像机组件
  9. 微信新用户暂停注册,预计恢复时间如下
  10. USB接口带不动USB移动硬盘的解决方法