qt安防源码:Qt编写安防视频监控系统14-本地回放
一、前言
在上一篇文章将视频文件存储好了,需要提供界面方便用户查询视频文件进行回放,其实这个回放就是播放历史存储的视频文件,并不是什么高大上的东西,视频回放在这个系统中分三种,第一种是本地回放,回放存储在客户端本地的视频文件;第二种是远程回放,采用NVR厂家提供的SDK开发包或者国标GB28181协议来回放存储在NVR上的视频文件;第三种是设备回放(统一放在设备播放模块),通过rtsp的格式来回放NVR上存储的视频文件,这个主要是方便第三方集成厂家开发,毕竟GB28181协议比较复杂,调试麻烦,不如直接指定特定的rtsp格式来回放视频,当然需要在请求的rtsp的地址中带上对应的用户验证信息,不然没法保证安全性。
如果存储采用的是ffmpeg,则回放该存储的视频文件,也是直接用ffmpeg打开文件播放即可,可以自由控制播放的速度,由于是裸流,默认很快的,在解码的时候都是使劲的解码绘制,所以这个特性刚好提供了速度控制的可能,自己在解码的时候休息一下下,就相当于慢点播放。如果存储采用的是vlc,则存储的是标准的视频文件,可以直接用其他播放器打开进行播放的,也可以用vlc打开本地文件播放的形式来播放。
本地回放模块,提供了查询界面,首先选择某个通道或者所有通道,再选择视频类型,有存储视频和报警视频两种,一般这两个都会分开文件夹存储的,优先级不一样,最后选择开始时间和结束时间,默认是按照天来计算的,还可以精确到时分秒,选择好以后单击查询按钮则会将符合条件的所有视频文件列出来,双击其中的一个文件就能启用播放,一个视频播放完毕,会自动跳到下一个文件继续播放,直到最后一个文件,界面上提供了播放暂停按钮,可以单击暂停当前播放的视频,还能看到播放的进度。
皮肤开源:[https://gitee.com/feiyangqingyun/QWidgetDemo](https://gitee.com/feiyangqingyun/QWidgetDemo) [https://github.com/feiyangqingyun/QWidgetDemo](https://github.com/feiyangqingyun/QWidgetDemo)
文件名称:styledemo
体验地址:[https://gitee.com/feiyangqingyun/QWidgetExe](https://gitee.com/feiyangqingyun/QWidgetExe) [https://github.com/feiyangqingyun/QWidgetExe](https://github.com/feiyangqingyun/QWidgetExe)
文件名称:bin_video_system.zip
二、功能特点1. 支持16画面切换,全屏切换等,包括1 4 6 8 9 13 16画面切换。
2. 支持alt enter全屏,esc退出全屏。
3. 自定义信息框 错误框 询问框 右下角提示框。
4. 17套皮肤样式随意更换,所有样式全部统一,包括菜单等。
5. 云台仪表盘鼠标移上去高亮,八个方位精准识别。
6. 底部画面工具栏(画面分割切换 截图声音等设置)移上去高亮。
7. 可在配置文件更改左上角logo 中文软件名称 英文软件名称。
8. 封装了百度地图,三维切换,设备点位,鼠标按下获取经纬度等。
9. 堆栈窗体,每个窗体都是个单独的qwidget,方便编写自己的代码。
10. 顶部鼠标右键菜单,可动态控制时间CPU 左上角面板 左下角面板 右上角面板 右下角面板的显示和隐藏,支持恢复默认布局。
11. 工具栏可以放置多个小图标和关闭图标。
12. 左侧右侧可拖动拉伸,并自动记忆宽高位置,重启后恢复。
13. 双击摄像机节点自动播放视频,双击节点自动依次添加视频,会自动跳到下一个,双击父节点自动添加该节点下的所有视频。
14. 摄像机节点拖曳到对应窗体播放视频,同时支持拖曳本地文件直接播放。
15. 视频画面窗体支持拖曳交换,瞬间响应。
16. 双击节点 拖曳节点 拖曳窗体交换位置,均自动更新url.txt。
17. 支持从url.txt中加载16通道视频播放,自动记忆最后通道对应的视频,软件启动后自动打开播放。
18. 右下角音量条控件,失去焦点自动隐藏,音量条带静音图标。
19. 集成百度地图,可以添加设备对应位置,自动生成地图,支持缩放和三维地图,提供地图风格选择,共12种风格。
20. 视频拖动到通道窗体外自动删除视频。
21. 鼠标右键可删除当前 所有视频,截图当前 所有视频。
22. 录像机管理、摄像机管理,可添加删除修改导入导出打印信息,立即应用新的设备信息生成树状列表,不需重启。
23. 在pro文件中可以自由开启是否加载地图。
24. 视频播放可选四种内核自由切换,vlc ffmpeg easyplayer 海康sdk,均可在pro中设置。
25. 可设置1 4 9 16画面轮询,可设置轮询间隔以及轮询码流类型等,直接在主界面底部工具栏右侧单击启动轮询按钮即可,再次单击停止轮询。
26. 默认超过10秒钟未操作自动隐藏鼠标指针。
27. 支持onvif搜素设备,支持任意onvif摄像机,包括但不限于海康大华宇视天地伟业华为等,支持onvif云台控制。
28. 高度可定制化,用户可以很方便的在此基础上衍生自己的功能,支持linux系统。
三、效果图四、核心代码void frmVideoPlayLocal::on_btnSelect_clicked(){ QDate dateStart = ui->dateStart->date(); QDate dateEnd = ui->dateEnd->date(); if (dateStart > dateEnd) { QUIHelper::showMessageBoxError("开始时间不能大于结束时间!", 3); return; } //将日期转换为日期时间计算相差的天数,超过60天则提示不用继续 QDateTime dateTimeStart = ui->dateStart->dateTime(); QDateTime dateTimeEnd = ui->dateEnd->dateTime(); if (dateTimeStart.daysTo(dateTimeEnd) >= 60) { QUIHelper::showMessageBoxError("每次最大只能查询60天内!", 3); return; } ui->listWidget->clear(); QString videoPath; if (ui->cboxType->currentText() == "存储视频") { videoPath = QString("%1/%2").arg(QUIHelper::appPath()).arg(DBData::VideoNormalPath); } else { videoPath = QString("%1/%2").arg(QUIHelper::appPath()).arg(DBData::VideoAlarmPath); } //获取所有文件夹名称,根据时间查询对应通道对应类型视频 //如果开始时间小于或者等于结束时间,则将开始时间对应文件夹下的视频文件添加到列表 //然后将开始时间加一天,知道大于结束时间 while (dateStart <= dateEnd) { QString savePath = QString("%1/%2").arg(videoPath).arg(dateStart.toString("yyyy-MM-dd")); QDir saveDir(savePath); QStringList filter; filter << "*.mp4" << "*.h264" ; QStringList files = saveDir.entryList(filter); foreach (QString file, files) { //如果是选择的所有通道,则不过滤视频文件 if (ui->cboxCh->currentText() == "所有通道") { QListWidgetItem *item = new QListWidgetItem(ui->listWidget); item->setText(file); item->setData(Qt::UserRole, QString(savePath)); } else { //对应通道的视频文件添加进来 QString videoCh = file.split("-").at(6).split(".").at(0); QString chName = QString("Ch%1").arg(ui->cboxCh->currentIndex()); if (videoCh == chName) { QListWidgetItem *item = new QListWidgetItem(ui->listWidget); item->setText(file); item->setData(Qt::UserRole, QString(savePath)); } } } dateStart = dateStart.addDays(1); } ui->labTip->setText(QString("共找到 %1 个").arg(ui->listWidget->count()));}void frmVideoPlayLocal::on_btnPlayVideo_clicked(){ if (ui->listWidget->currentRow() < 0) { return; } bool check = ui->btnPlayVideo->isChecked(); if (!check) { IconHelper::Instance()->setIcon(ui->btnPlayVideo, 0xf28d, btnRadius); widget->next(); timerPlay->start(); } else { IconHelper::Instance()->setIcon(ui->btnPlayVideo, 0xf144, btnRadius); widget->pause(); timerPlay->stop(); }}void frmVideoPlayLocal::on_listWidget_doubleClicked(){ timerPlay->stop(); QListWidgetItem *item = ui->listWidget->currentItem(); QString file = QString("%1/%2").arg(item->data(Qt::UserRole).toString()).arg(item->text()); //将文件路径转为操作系统可以识别的路径,在windows下Qt之外的程序调用路径必须转换 file = QDir::toNativeSeparators(file); //存储的视频不能获取视频长度,这里另想高招,取文件的创建时间,用修改时间减去创建时间就是长度 QFileInfo mp4File(file); QDateTime creatTime = mp4File.created(); QDateTime lastTime = mp4File.lastModified(); //如果创建时间大于最后修改时间,说明文件长度为0或者是复制过来的而不是正常的存储文件. if (creatTime >= lastTime) { QUIHelper::showMessageBoxError("非正常存储视频文件,请重新选择!"); return; } //得到时间差,单位毫秒 qint64 milliSecondTime = creatTime.msecsTo(lastTime); int hour = milliSecondTime / (60 * 60 * 1000); int minute = (milliSecondTime - hour * 60 * 60 * 1000) / (60 * 1000); int seconds = (milliSecondTime - hour * 60 * 60 * 1000 - minute * 60 * 1000) / 1000; if (seconds >= 60) { seconds = seconds % 60; minute = seconds / 60; } if (minute >= 60) { minute = minute % 60; hour = minute / 60; } //播放时长重新计数 hourPlay = 0; minutePlay = 0; secondsPlay = 0; secondsPlayCount = 0; timerPlay->start(); //重新设置进度条和总时长 currentVideoLenght = milliSecondTime / 1000; ui->slider->setMinimum(0); ui->slider->setMaximum(currentVideoLenght); ui->slider->setValue(0); ui->labTimeAll->setText(QString("总时长: %1时%2分%3秒").arg(hour).arg(minute).arg(seconds)); //先释放上一个播放的视频,再打开当前播放的视频 widget->setUrl(file); widget->restart(); currentVideo = file; ui->btnPlayVideo->setEnabled(true); ui->btnPlayVideo->setChecked(false); IconHelper::Instance()->setIcon(ui->btnPlayVideo, 0xf28d, btnRadius);}
- 10-19小米最值得购买的百元以内产品:必买,不到百元这六款小米好物早买早享受
- 11-01历年学院改大学:从,学院更名
- 12-24世界油画艺术欣赏名画解密:魔都100他被称为鬼才画家
- 11-28门牌吉凶对照表 因人而异的吉凶门牌号
- 05-13tiffany是高奢还是顶奢:那些戴Tiffany,T1的致命女人们
- 01-06android系统安卓11,安卓新系统改名为,Android10
- 04-21洗澡时用什么搓泥可以搓干净?洗澡必须使劲搓才算洗干净
- 12-16怎么在王者荣耀中看到视野盲区?飞常会玩,王者荣耀多指视野技巧解析
- 03-15真正的古董和古玩的区别:古董鉴藏的哪些鲜为人知的真相
- 03-12湖南邵东车马灯表演最新视频,湖南邵阳邵东贺年车马灯火了
- 12-24100个经典逆向思维故事,10个逆向思维小故事,让你获得不一样的成功
- 01-28长相思思乡的诗句:诗词赏析,朴实的思乡之作静夜思
- 01-20为啥小猫咪一直喵喵叫还蹭我:小猫咪刚领回家总是叫个不停
- 03-27孕妇建档什么时间最合适?孕妇须知孕期建档什么时候去
- 01-23如何更好的游戏化教学?如何用游戏化思维构建
- 05-1310大奢侈内衣品牌,五大奢侈内衣品牌排行
热门
推荐
- 1锅包肉的简单做法218
- 2人生列车作文345
- 3为什么喜欢夏天的理由_为什么夏天要给孩子补点锌?286
- 4陌陌繁体字个性签名212
- 5和领导乘电梯礼仪217
- 6试用期员工转正工作总结范文360
- 7申报小学高级职称教师述职报告263
- 8沈括简介及故事179