Qt/C++编写视频监控系统82-自定义音柱显示

news2024/11/15 21:50:38

一、前言

通过音柱控件实时展示当前播放的声音产生的振幅的大小,得益于音频播放组件内置了音频振幅的计算,可以动态开启和关闭,开启后会对发送过来的要播放的声音数据,进行运算得到当前这个音频数据的振幅,类似于分贝,分贝越大,听到的声音越大,振幅越大。在如何摆放音柱控件这个问题上,考虑过多种方案,比如一开始做的是固定放在视频控件的右侧,也就是在一个垂直布局中先放一个视频控件,然后放左通道音柱,最后放一个右通道音柱,三个控件之间设置好间距。后面用户又提出来直接音柱控件悬浮在视频控件上方,这样可以节约位置,以便视频控件争取最大的地方展示,所以近期又专门重新搞了下,音柱可以放置在左侧、右侧、顶部、底部、两侧、悬浮等位置,然后还可以设置音柱的尺寸,如果是垂直摆放对应尺寸就是宽度,如果是上下摆放对应尺寸就是高度,还有个难点就是纯音频的通道,音量条需要摆放在中间位置,比如音量条左右两侧是一个弹簧,音量条尺寸取宽度的四分之一,这样看起来就非常美观了。

由于视频控件还有悬浮条,所以这个音柱的摆放位置,还需要留出足够的位置给悬浮条展示,然而呢悬浮条又有多种位置,比如也可以设置在底部,所以需要根据悬浮条的位置,再留出对应的间隙。在Qt的便利性,要设计这样一个带视频带悬浮带音柱,而且还支持非常灵活的各种参数设置,还是非常方便的,比如就新建个frmVideoWidgetVolume带音柱的视频窗体,悬浮条也是一个独立的widget,根据尺寸变化对应移来移去。音柱控件这边,通过表格布局来插入对应的控件。比如需要两侧显示音柱,则先插入左声道音柱,然后插入视频控件,最后插入右声道音柱控件。难点就在纯音频的音道控件,他需要根据尺寸占比自动拉伸,而且一个窗体需要根据打开的地址来区分当前是否是纯音频,所以需要在解码完成和结束的时候去做判断处理,打完收工。

二、效果图

在这里插入图片描述

三、体验地址

  1. 国内站点:https://gitee.com/feiyangqingyun
  2. 国际站点:https://github.com/feiyangqingyun
  3. 个人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
  4. 体验地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取码:01jf 文件名:bin_video_system。

四、相关代码

#include "frmvideowidgetvolume.h"
#include "ui_frmvideowidgetvolume.h"
#include "qthelper.h"
#include "videowidgetx.h"
#include "barvolume.h"

frmVideoWidgetVolume::frmVideoWidgetVolume(int position, VideoWidget *videoWidget, QWidget *parent) : QWidget(parent), ui(new Ui::frmVideoWidgetVolume)
{
    ui->setupUi(this);

    this->position = position;
    this->videoWidget = videoWidget;
    bgText = videoWidget->getBgText();

    isVertical = true;
    if (position == 2 || position == 4) {
        isVertical = false;
    }

    //实例化音柱控件并设置方向
    leftVolume = new BarVolume;
    rightVolume = new BarVolume;
    leftVolume->setVertical(isVertical);
    rightVolume->setVertical(isVertical);

    //实例化布局并设置边距间距
    QGridLayout *layout = new QGridLayout(this);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(3);

    //将音柱控件和视频控件插入到对应位置/可以自行拓展各种布局
    if (position == 1) {
        layout->addWidget(leftVolume, 0, 0);
        layout->addWidget(rightVolume, 0, 1);
        layout->addWidget(videoWidget, 0, 2);
    } else if (position == 2) {
        layout->addWidget(leftVolume, 0, 0);
        layout->addWidget(rightVolume, 1, 0);
        layout->addWidget(videoWidget, 2, 0);
    } else if (position == 3) {
        layout->addWidget(videoWidget, 0, 0);
        layout->addWidget(leftVolume, 0, 1);
        layout->addWidget(rightVolume, 0, 2);
    } else if (position == 4) {
        layout->addWidget(videoWidget, 0, 0);
        layout->addWidget(leftVolume, 1, 0);
        layout->addWidget(rightVolume, 2, 0);
    } else if (position == 5) {
        layout->addWidget(leftVolume, 0, 0);
        layout->addWidget(videoWidget, 0, 1);
        layout->addWidget(rightVolume, 0, 2);
    } else if (position == 6) {
        //实例化弹簧控件
        spaceLeft = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Preferred);
        spaceCenter = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Preferred);
        spaceRight = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Preferred);

        //实例化布局并插入控件
        hlayout = new QHBoxLayout;
        hlayout->addWidget(leftVolume);
        hlayout->addItem(spaceCenter);
        hlayout->addWidget(rightVolume);
        videoWidget->setLayout(hlayout);
        layout->addWidget(videoWidget);
    }

    //关联音频振幅信号
    connect(videoWidget, SIGNAL(sig_receiveLevel(qreal, qreal)), this, SLOT(receiveLevel(qreal, qreal)));
    //打开和关闭后需要清空下(有可能残留上一次的数据)
    connect(videoWidget, SIGNAL(sig_receivePlayStart(int)), this, SLOT(reset()));
    connect(videoWidget, SIGNAL(sig_receivePlayFinsh()), this, SLOT(reset()));
    //音柱窗体参数变化后需要重置
    connect(AppEvent::Instance(), SIGNAL(changeVolumeWidget()), this, SLOT(reset()));
}

frmVideoWidgetVolume::~frmVideoWidgetVolume()
{
    delete ui;
}

void frmVideoWidgetVolume::resizeEvent(QResizeEvent *)
{
    int width = this->width();
    int height = this->height();

    //根据宽度动态设置音量条宽度或者高度/也可以设置成固定值
    int size = (isVertical ? width : height);
    if (AppConfig::VolumeSize == 0) {
        size = size * 0.05;
        size = (size > 20 ? 20 : size);
    } else {
        size = AppConfig::VolumeSize;
    }

    if (isVertical) {
        leftVolume->setMaximumWidth(size);
        rightVolume->setMaximumWidth(size);
    } else {
        leftVolume->setMaximumHeight(size);
        rightVolume->setMaximumHeight(size);
    }

    //根据高度动态设置音量格子数量(一般高度越小格子数越少)
    int step = height / (position == 6 ? 10 : 6);
    leftVolume->setStep(step);
    rightVolume->setStep(step);

    //根据音柱位置摆放控件
    if (position == 6) {
        if (videoWidget->getIsRunning() && videoWidget->getVideoThread()->getIsOk()) {
            leftVolume->show();
            rightVolume->show();

            //根据悬浮条的位置留出空余的地方
            int offset = 35;
            if (AppConfig::BannerPosition == 1) {
                hlayout->setContentsMargins(9, 9, 9, offset);
            } else if (AppConfig::BannerPosition == 2) {
                hlayout->setContentsMargins(offset, 9, 9, 9);
            } else if (AppConfig::BannerPosition == 3) {
                hlayout->setContentsMargins(9, 9, offset, 9);
            } else {
                hlayout->setContentsMargins(9, offset, 9, 9);
            }

            //先把布局中的挨个移除
            hlayout->removeItem(spaceLeft);
            hlayout->removeItem(spaceCenter);
            hlayout->removeItem(spaceRight);
            hlayout->removeWidget(leftVolume);
            hlayout->removeWidget(rightVolume);

            //纯音频需要占用比较大的面积
            if (videoWidget->getOnlyAudio()) {
                videoWidget->setBgText("");
                size = width / 4;
                leftVolume->setMaximumWidth(size);
                rightVolume->setMaximumWidth(size);
                leftVolume->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
                rightVolume->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
                hlayout->addItem(spaceLeft);
                hlayout->addWidget(leftVolume);
                hlayout->addWidget(rightVolume);
                hlayout->addItem(spaceRight);
            } else {
                leftVolume->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
                rightVolume->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
                hlayout->addWidget(leftVolume);
                hlayout->addItem(spaceCenter);
                hlayout->addWidget(rightVolume);
            }
        } else {
            leftVolume->hide();
            rightVolume->hide();
            videoWidget->setBgText(bgText);
        }
    }
}

void frmVideoWidgetVolume::reset()
{
    leftVolume->clear();
    rightVolume->clear();
    this->resizeEvent(NULL);
}

void frmVideoWidgetVolume::receiveLevel(qreal leftLevel, qreal rightLevel)
{
    leftVolume->setValue(leftLevel);
    rightVolume->setValue(rightLevel);
}

五、功能特点

5.1 软件模块

  1. 视频监控模块,各种停靠小窗体子模块,包括设备列表、图文警情、窗口信息、云台控制、预置位、巡航设置、设备控制、悬浮地图、网页浏览等。
  2. 视频回放模块,包括本地回放、远程回放、设备播放、图片回放、视频上传等。
  3. 电子地图模块,包括图片地图、在线地图、离线地图、路径规划等。
  4. 日志查询模块,包括本地日志、设备日志等。
  5. 系统设置模块,包括系统设置(基本设置、视频参数、数据库设置、地图配置、串口配置等)、录像机管理、摄像机管理、轮询配置、录像计划、用户管理等。

5.2 基础功能

  1. 支持各种视频流(rtsp、rtmp、http等)、视频文件(mp4、rmvb、avi等)、本地USB摄像机播放。
  2. 支持多画面切换,包括1、4、6、8、9、13、16、25、36、64画面切换。
  3. 支持全屏切换,多种切换方式包括鼠标右键菜单、工具栏按钮、快捷键(alt+enter全屏,esc退出全屏)。
  4. 支持视频轮询,包括1、4、9、16画面轮询,可设置轮询分组(轮询预案)、轮询间隔、码流类型等。
  5. 支持onvif协议,包括设备搜索、云台控制、预置位、设备控制(图片参数、校对时间、系统重启,抓拍图片等)。
  6. 支持权限管理,不同的用户可以对应不同的模块权限,比如删除日志、关闭系统等。
  7. 数据库支持多种,包括sqlite、mysql、sqlserver、postgresql、oracle、人大金仓等。
  8. 本地USB摄像机支持设置分辨率、帧率等参数。
  9. 所有停靠模块都自动生成对应的菜单用来控制显示和隐藏,在标题栏右键可以弹出。
  10. 支持显示所有模块、隐藏所有模块、复位普通布局、复位全屏布局。
  11. 双击设备弹出实时预览视频,支持图片地图、在线地图、离线地图等。
  12. 摄像机节点拖曳到对应窗体播放视频,同时支持拖曳本地文件直接播放。
  13. 删除视频支持鼠标右键删除、悬浮条关闭删除、拖曳到视频监控面板外删除等多种方式。
  14. 图片地图上设备按钮可自由拖动,自动保存位置信息。百度地图上可以鼠标单击获取经纬度信息,用来更新设备位置。
  15. 视频监控面板窗体中任意通道支持拖曳交换,瞬间响应。
  16. 封装了百度地图,视图切换,运动轨迹,设备点位,鼠标按下获取经纬度等。
  17. 双击节点、拖曳节点、拖曳窗体交换位置等操作,均自动更新保存最后的播放地址,下次软件打开自动应用。
  18. 右下角音量条控件,失去焦点自动隐藏,音量条带静音图标。
  19. 支持视频截图,可指定单个或者对所有通道截图,底部小工具栏也有截图按钮。
  20. 支持超时自动隐藏鼠标指针、自动全屏机制。
  21. 支持onvif云台控制,可上下左右移动云台摄像机,包括复位和焦距调整等。
  22. 支持onvif预置位,可以添加、删除、修改预置位,可以调用起始位。
  23. 支持onvif图像参数设置,包括明亮度、对比度、饱和度、尖锐度等。
  24. 支持onvif其他操作,包括抓图、网络设置、校时、重启、事件订阅等。
  25. 支持任意onvif摄像机,包括但不限于海康、大华、宇视、天地伟业、华为等。
  26. 可保存视频,可选定时存储或者单文件存储,可选存储间隔时间。
  27. 可设置视频流通信方式tcp+udp,可设置视频解码是速度优先、质量优先、均衡等。
  28. 可设置软件中文名称、英文名称、LOGO图标等。
  29. 存储的视频文件支持导出到指定目录,支持批量上传到服务器。
  30. 完善的录像计划设置,支持每个通道7 * 24小时每半小时设置是否存储录像。

5.3 特色功能

  1. 主界面采用停靠窗体模式,各种组件以小模块的形式加入,可自定义任意模块加入。
  2. 停靠模块可拖动任意位置嵌入和悬浮,支持最大化全屏,支持多屏幕。
  3. 双重布局文件存储机制,正常模式、全屏模式都对应不同的布局方案,自动切换和保存,比如全屏模式可以突出几个模块透明显示在指定位置,更具科幻感现代化。
  4. 原创onvif协议机制,采用底层协议解析(udp广播搜索+http请求执行命令)更轻量易懂易学习拓展,不依赖任何第三方组件比如gsoap。
  5. 原创数据导入、导出、打印机制,跨平台不依赖任何组件,瞬间导出数据。
  6. 内置多个原创组件,宇宙超值超级牛逼,包括数据导入导出组件(导出到xls、pdf、打印)、数据库组件(数据库管理线程、自动清理数据线程、万能分页、数据请求等)、地图组件、视频监控组件、文件多线程收发组件、onvif通信组件、通用浏览器内核组件等。
  7. 自定义信息框+错误框+询问框+右下角提示框(包含多种格式)等。
  8. 精美换肤,高达17套皮肤样式随意更换,所有样式全部统一,包括菜单等。
  9. 视频控件悬浮条可以自行增加多个按钮,监控界面底部小工具栏也可自行增加按钮。
  10. 双击摄像机节点自动播放视频,双击节点自动依次添加视频,会自动跳到下一个,双击父节点自动添加该节点下的所有视频。可选主码流、子码流。
  11. 录像机管理、摄像机管理,可添加删除修改导入导出打印信息,立即应用新的设备信息生成树状列表,不需重启。
  12. 可选多种内核自由切换,ffmpeg、vlc、mpv等,均可在pro中设置。推荐用ffmpeg,跨平台最多,默认提供好了linux和mac平台上编译好的库。
  13. 支持硬解码,可设置硬解码类型(qsv、dxva2、d3d11va等)。
  14. 默认采用opengl绘制视频,超低的CPU资源占用,支持yuyv和nv12两种格式绘制,性能爆表。
  15. 标签和图形信息支持三种绘制方式,绘制到遮罩层、绘制到图片、源头绘制(对应信息可以存储到文件)。
  16. 高度可定制化,用户可以很方便的在此基础上衍生自己的功能,比如增加自定义模块,增加运行模式、机器人监控、无人机监控、挖掘机监控等。
  17. 支持xp、win7、win10、win11、linux、mac、各种国产系统(UOS、中标麒麟、银河麒麟等)、嵌入式linux等系统。
  18. 注释完整,项目结构清晰,超级详细完整的使用开发手册,精确到每个代码文件的功能说明,不断持续迭代版本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1353973.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

初始数字孪生

文章目录 概念定义 架构框图 基本要求 功能要求 服务应用 参考文献 概念定义 数字孪生(digital twin),是指具有保证物理状态和虚拟状态之间以适当速率和精度同步的数据连接的特定目标实体的数字化表达。 架构框图 数字孪生的整体架构&a…

玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— DevEco Studio下载与安装

一、下载DevEco Studio IDE开发工具 1. 登录鸿蒙官网 网址为: ​​​​​​​华为HarmonyOS智能终端操作系统官网 | 应用设备分布式开发者生态 页面如下: 2. 搜索“DevEco Studio IDE” 点击右上角的“请输入关键词”,在其中搜索“DevEc…

Termius for Mac/Win:一款功能强大的终端模拟器、SSH 和 SFTP 客户端软件

随着远程工作和云技术的普及,对于高效安全的远程访问和管理服务器变得至关重要。Termius,一款强大且易用的终端模拟器、SSH 和 SFTP 客户端软件,正是满足这一需求的理想选择。 Termius 提供了一站式的解决方案,允许用户通过单一平…

钡铼分布式IO在玻璃制造中的实时数据采集与监控应用介绍

导读 玻璃行业多年来一直广泛使用 PLC 来帮助管理生产过程所需的精确材料比例,完全依赖其PLC进行数据采集与控制,并且大量依靠人工来操作,所以这些高成本推动了对成本较低的替代方案的需求。 场景描述 某玻璃厂生产的玻璃生产包括配料段、熔…

Excel 插件:ASAP Utilities Crack

ASAP Utilities是一款功能强大的 Excel 插件,填补了 Excel 的空白。在过去的 20 年里,我们的加载项已经发展成为世界上最受欢迎的 Microsoft Excel 加载项之一。 ASAP Utilities 中的功能数量(300 多个)可能看起来有点令人眼花缭乱…

2024.1.2 Redis 数据类型 Stream、Geospatial、HyperLogLog、Bitmaps、Bitfields 简介

目录 引言 Stream 类型 Geospatial 类型 HyperLogLog 类型 Bitmaps 类型 Bitfields 类型 引言 Redis 最关键(应用广泛、频繁使用)的五个数据类型 StringListHashSetZSet 下文介绍的数据类型一般适合在特定的场景中使用! Stream 类型 St…

守护进程“独辟蹊径”

守护进程“独辟蹊径” 一、前言二、实际运用2.1 知识介绍2.2 单机库场景应用2.2.1 配置dmwatcher.ini2.2.2 注册后台守护服务2.2.3 配置dmmal.ini2.2.4 配置归档和守护OGUID2.2.5 开启mal2.2.6 启动守护2.2.7 测试dmserver异常退出 三、总结 DM技术交流QQ群:9401242…

alibabaCloud学习笔记01(小滴课堂)

微服务架构常见的核心组件 讲解业务微服务架构常见解决方案 讲解AlibabaCloud核心组件介绍 创建数据库。 建表: 添加数据: 再建个用户库: 建表: 插入数据: 创建订单库: 建表: 创建项目&#x…

【ikbp】数据可视化DataV

天天查询一些数据,希望来一个托拉拽的展示,部署体验一下可视化大屏 快速搭建快速查询实时更新简单易用 启动服务 数据可视化 静态查询 配置数据 过滤数据 分享

目标检测-One Stage-RetinaNet

文章目录 前言一、RetinaNet的网络结构和流程二、RetinaNet的创新点Balanced Cross EntropyFocal Loss 总结 前言 根据前文目标检测-One Stage-YOLOv2可以看出YOLOv2的速度和精度都有相当程度的提升,但是One Stage目标检测模型仍存在一个很大的问题: 前…

计算机组成原理-总线操作和定时(同步定时方式 异步定时方式 半同步通信 分离式通信)

文章目录 总览总线传输的四个阶段同步定时方式读命令小结 异步定时方式半同步通信分离式通信小结 总览 总线传输的四个阶段 同步定时方式 读命令 总线传输分为多个时钟周期 首先CPU在T1阶段发出地址信息,此时地址线信号改变 CPU在T2阶段发出读命令,此时…

【Fastadmin】系统配置自定义键值组件

目录 1.修改config表的extend字段为text类型,否则会出现长度不足报错 2.添加配置 3.参考代码 图1代码: 图2代码: 图3代码: html部分: js部分:assets/js/general/config.js 参考文档: FastAdmin是一…

循环与基础函数

循环与函数 1.循环的三种方式2.循环的中断与空语句3.函数的定义与使用4.参数的作用域5.指针6.总结 1.循环的三种方式 我们最熟悉的循环为for和while,这两种循环方式在Python系列介绍过。在C中,循环的基本逻辑同Python是类似的。c中while循环的语法如下&…

词嵌入位置编码的实现(基于pytorch)

背景介绍 在transformers架构当中,对于词向量的输入需要加上原本词对应的位置信息,作为输入到模型中训练的input,那具体的位置编码如何实现呢?本篇博客就跟大家一起分享一下对应的步骤 位置编码的公式 对于词向量的位置编码的方…

C++上位软件通过LibModbus开源库和西门子S7-1200/S7-1500/S7-200 PLC进行ModbusTcp 和ModbusRTU 通信

前言 一直以来上位软件比如C等和西门子等其他品牌PLC之间的数据交换都是大家比较头疼的问题,尤其是C上位软件程序员。传统的方法一般有OPC、Socket 等,直到LibModbus 开源库出现后这种途径对程序袁来说又有了新的选择。 Modbus简介 Modbus特点 1 &#…

Navicat、Microsoft SQL Server Management Studio设置ID自增

一、Navicat中mysql数据库设置Id自增 (1)第一步 (2)第二步 二、Microsoft SQL Server Management Studio中Sqlservice数据库Id自增 (1)第一步 (2)第二步 (3&#xff09…

RuoYi-Cloud-Plus使用minio进行文件上传图片后无法预览解决_修改minio配置minio桶权限---SpringCloud工作笔记198

在文件管理的位置,发现刚刚上传的图片文件,会显示 预览图片失败 后来经过多方查看,发现是minio的配置的问题 可以从这里: 可以看到首先登录RuoYi-Cloud-Plus系统然后,打开文件管理页面可以看到,当上传了图片文件以后 显示文件展示中,文件预览失败,那么这个时候,去修改minio的配…

element中Table表格控件实现单选功能、多选功能、两种分页方式

目录 1、Table表格控件实现单选功能2、Table控件和Pagination控件实现多选和两种分页方式方法一&#xff1a;使用slice方法方法二&#xff1a;多次调用接口 1、Table表格控件实现单选功能 <template><div><!-- highlight-current-row 是否要高亮当前行 -->…

IMU用于无人机故障诊断

最近&#xff0c;来自韩国的研究团队通过开发以IMU为中心的数据驱动诊断方法&#xff0c;旨在多旋翼飞行器可以自我评估其性能&#xff0c;即时识别和解决推进故障。该方法从单纯的常规目视检查跃升为复杂的诊断细微差别&#xff0c;标志着无人机维护的范式转变。 与依赖额外传…

Elasticsearch:如何使用 Elasticsearch 进行排序

虽然你在唱这首歌时可能会想象圣诞老人&#xff0c;但欧洲民间传说&#xff0c;尤其是阿尔卑斯地区的民间传说&#xff0c;有两个传奇人物圣尼古拉斯和坎普斯。 象征着慷慨和善良的圣尼古拉斯&#xff0c;在 12 月 6 日 为乖巧的孩子们带来礼物和欢乐&#xff01; 相比之下&…