QT实现在线流媒体播放平台

文章目录

  • QT实现在线流媒体播放平台
    • 简介
    • 开发视频
      • ffmpeg下载
      • SimpleVideoPlayer.h
      • SimpleVideoPlayer.cpp
    • 开发音频
    • 添加功能
      • 打开文件夹
      • 播放暂停
      • 播放上下一首
      • 选择倍速
    • 效果展示
    • 项目下载

QT实现在线流媒体播放平台

简介

Qt是一种流行的C++开发框架,它提供了用于构建图形用户界面(GUI)和跨平台应用程序的工具和库。Qt具有广泛的应用范围,可以用于开发桌面应用程序、移动应用程序和嵌入式系统等。Qt具有丰富的多媒体功能,包括音频和视频处理能力。

在使用Qt进行在线流媒体开发时,我们可以结合FFmpeg和QMediaPlayer来实现强大的音视频处理和播放功能。首先,可以使用FFmpeg解码音视频文件或流,提取音频和视频数据。然后,可以使用QMediaPlayer加载音频和视频数据,并通过其播放控制接口实现音视频的同步播放。此外,可以使用Qt的图形界面开发能力,创建用户友好的界面,显示视频内容,并提供交互控制。

开发视频

FFmpeg是一个开源的多媒体框架,它提供了一套用于处理音视频的工具和库。FFmpeg支持广泛的音视频格式和编解码器,能够对音视频进行解码、编码、转换和处理等操作。在在线流媒体应用中,FFmpeg通常用于处理音视频文件或流,提取其中的音频和视频数据,进行解码和编码,以及应用特效和滤镜等。

ffmpeg下载

如果你的qt版本是32位,下载的FFmpeg是64位,则可能识别不了函数
在这里我提供了64位和32位的FFmpeg下载链接

32位链接: https://pan.baidu.com/s/1wBAv6yYYa_9n64wzmHdO2w
提取码:0703

64位链接: https://pan.baidu.com/s/1aEHWpbTQkhVA30KtfviYjA
提取码:0703

SimpleVideoPlayer.h

#ifndef SIMPLEVIDEOPLAYER_H
#define SIMPLEVIDEOPLAYER_H#include <QThread>
#include <QMainWindow>
#include <QImage>extern "C"
{#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#include <libavutil/imgutils.h>
}class SimpleVideoPlayer : public QThread
{Q_OBJECTpublic:explicit SimpleVideoPlayer();~SimpleVideoPlayer();void setVideo(const QString &videoPath){this->_videoPath = videoPath;}inline void play();enum class PlayerState {Playing,Paused,Stopped};void togglePlayPause();void changeState();void setPlaybackSpeed(QString speed);
signals:void sigCreateVideoFrame(QImage image);protected:void run();private:QString _videoPath;PlayerState _state = PlayerState::Playing;QString speedVideo = "1x";
};#endif // SIMPLEVIDEOPLAYER_H

SimpleVideoPlayer.cpp

#include "SimpleVideoPlayer.h"
#include <iostream>
#include <QDebug>SimpleVideoPlayer::SimpleVideoPlayer()
{}SimpleVideoPlayer::~SimpleVideoPlayer()
{}void SimpleVideoPlayer::play()
{start();
}void SimpleVideoPlayer::togglePlayPause()
{if (_state == PlayerState::Playing) {_state = PlayerState::Paused;} else {_state = PlayerState::Playing;}
}void SimpleVideoPlayer::changeState()
{if(_state == PlayerState::Playing || _state == PlayerState::Paused){_state = PlayerState::Stopped;}
}void SimpleVideoPlayer::setPlaybackSpeed(QString speed)
{speedVideo = speed;
}void SimpleVideoPlayer::run()
{_state = PlayerState::Playing;if (_videoPath.isNull()){return;}char *file1 = _videoPath.toUtf8().data();//编解码器的注册,最新版本不需要调用//av_register_all();//描述多媒体文件的构成及其基本信息AVFormatContext *pAVFormatCtx = avformat_alloc_context();if (avformat_open_input(&pAVFormatCtx, file1, NULL, NULL) != 0){std::cout<<"open file fail"<<std::endl;avformat_free_context(pAVFormatCtx);return;}//读取一部分视音频数据并且获得一些相关的信息if (avformat_find_stream_info(pAVFormatCtx, NULL) < 0){std::cout<<"avformat find stream fail"<<std::endl;avformat_close_input(&pAVFormatCtx);return;}int iVideoIndex = -1;for (uint32_t i = 0; i < pAVFormatCtx->nb_streams; ++i){//视频流if (pAVFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){iVideoIndex = i;break;}}if (iVideoIndex == -1){std::cout<<"video stream not find"<<std::endl;avformat_close_input(&pAVFormatCtx);return;}//获取视频流的编解码器上下文的数据结构AVCodecContext *pAVCodecCtx = avcodec_alloc_context3(NULL);if (!pAVCodecCtx) {fprintf(stderr, "Could not allocate codec context\n");exit(1);}if (avcodec_parameters_to_context(pAVCodecCtx, pAVFormatCtx->streams[iVideoIndex]->codecpar) < 0) {fprintf(stderr, "Could not copy codec parameters\n");exit(1);}//编解码器信息的结构体const AVCodec *pAVCodec = avcodec_find_decoder(pAVCodecCtx->codec_id);if (pAVCodec == NULL){std::cout<<"not find decoder"<<std::endl;return;}//初始化一个视音频编解码器if (avcodec_open2(pAVCodecCtx, pAVCodec, NULL) < 0){std::cout<<"avcodec_open2 fail"<<std::endl;return;}//AVFrame 存放从AVPacket中解码出来的原始数据AVFrame *pAVFrame = av_frame_alloc();AVFrame *pAVFrameRGB = av_frame_alloc();//用于视频图像的转换,将源数据转换为RGB32的目标数据SwsContext *pSwsCtx = sws_getContext(pAVCodecCtx->width, pAVCodecCtx->height, pAVCodecCtx->pix_fmt,pAVCodecCtx->width, pAVCodecCtx->height, AV_PIX_FMT_RGB32,SWS_BICUBIC, NULL, NULL, NULL);int iNumBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB32, pAVCodecCtx->width, pAVCodecCtx->height,1);uint8_t *pRgbBuffer = (uint8_t *)(av_malloc(iNumBytes * sizeof(uint8_t)));//为已经分配的空间的结构体AVPicture挂上一段用于保存数据的空间av_image_fill_arrays(pAVFrameRGB->data, pAVFrameRGB->linesize, pRgbBuffer, AV_PIX_FMT_RGB32, pAVCodecCtx->width, pAVCodecCtx->height,1);//AVpacket 用来存放解码之前的数据AVPacket packet;av_new_packet(&packet, pAVCodecCtx->width * pAVCodecCtx->height);//读取码流中视频帧while (av_read_frame(pAVFormatCtx, &packet) >= 0){if (_state == PlayerState::Stopped) {qDebug()<<"当前音乐已终止";break;}if (_state == PlayerState::Paused) {QThread::msleep(600); // Sleep for 600ms 线程休息continue;}if (packet.stream_index != iVideoIndex){av_packet_unref(&packet);continue;}// 发送数据包到解码器if (avcodec_send_packet(pAVCodecCtx, &packet) < 0){std::cout << "Error sending packet for decoding." << std::endl;av_packet_unref(&packet);continue;}// 从解码器接收解码后的帧while (avcodec_receive_frame(pAVCodecCtx, pAVFrame) == 0){// 转换像素格式sws_scale(pSwsCtx, (uint8_t const * const *)pAVFrame->data, pAVFrame->linesize, 0, pAVCodecCtx->height, pAVFrameRGB->data, pAVFrameRGB->linesize);// 构造QImageQImage img(pRgbBuffer, pAVCodecCtx->width, pAVCodecCtx->height, QImage::Format_RGB32);// 绘制QImageemit sigCreateVideoFrame(img);}av_packet_unref(&packet);double fps = av_q2d(pAVFormatCtx->streams[iVideoIndex]->r_frame_rate);int delay = 900.0 / fps;if(speedVideo == "2x"){msleep(delay / 2);}else if(speedVideo == "0.5x"){msleep(delay * 2);}else{msleep(delay);}//msleep(15);}//资源回收/*av_free(pAVFrame);av_free(pAVFrameRGB);sws_freeContext(pSwsCtx);avcodec_close(pAVCodecCtx);avformat_close_input(&pAVFormatCtx);*/av_frame_free(&pAVFrame);av_frame_free(&pAVFrameRGB);sws_freeContext(pSwsCtx);avcodec_free_context(&pAVCodecCtx);avformat_close_input(&pAVFormatCtx);}

开发音频

QMediaPlayer是Qt自带的多媒体播放器类,它提供了简单易用的接口,用于播放音频和视频文件。QMediaPlayer支持多种音视频格式,并且可以通过网络流式传输音视频内容。它具有播放、暂停、停止、跳转和调整音量等常见的播放控制功能。此外,QMediaPlayer还提供了信号和槽机制,可用于捕获播放状态的变化和处理用户交互事件。

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);this->setWindowTitle("在线播放平台");//comboBox 数据居中ui->comboBox->setStyleSheet("QComboBox QAbstractItemView { text-align: center; }");/*QMediaPlayer * m_player;m_player = new QMediaPlayer(this);QString strPlayer = "D:/QT.study/onlinePlay/qiFengLe";m_player->setMedia(QUrl::fromLocalFile(strPlayer));m_player->setVolume(50);m_player->play();*///QPushButton *openFileButton = new QPushButton("打开文件", this);//setCentralWidget(openFileButton);connect(ui->openFileButton, &QPushButton::clicked, this, &MainWindow::openFileDialog);_simpleVp = new SimpleVideoPlayer();// 创建媒体播放器player = new QMediaPlayer;//_simpleAp = new audioPlayer();connect(_simpleVp,SIGNAL(sigCreateVideoFrame(QImage)),this,SLOT(sigGetVideoFrame(QImage)));connect(ui->Slider,&QSlider::valueChanged,this,&MainWindow::changeAudio);connect(ui->startBtn,&QPushButton::clicked,this,&MainWindow::startPlay);connect(ui->pauseButton , &QPushButton::clicked, this->_simpleVp, &SimpleVideoPlayer::togglePlayPause);connect(ui->boxBS, &QComboBox::currentTextChanged, this, &MainWindow::onSpeedChanged);//下一首歌曲connect(ui->nextButton,&QPushButton::clicked,this->_simpleVp,&SimpleVideoPlayer::changeState);connect(ui->nextButton,&QPushButton::clicked,this,&MainWindow::nextVideo);//上一首歌曲connect(ui->previousBtn,&QPushButton::clicked,this->_simpleVp,&SimpleVideoPlayer::changeState);connect(ui->previousBtn,&QPushButton::clicked,this,&MainWindow::previousVideo);//暂停播放connect(ui->pauseButton,&QPushButton::clicked,this,&MainWindow::pauseAudio);//增加MV曲目ui->comboBox->addItem("起风了----------买辣椒也用券");ui->comboBox->addItem("悬溺------------葛东琪");ui->comboBox->addItem("平凡之路--------朴树");ui->comboBox->addItem("把回忆拼好给你---------王贰浪");ui->comboBox->addItem("带我去找夜生活---------告五人");//增加倍速ui->boxBS->addItem("1x");ui->boxBS->addItem("0.5x");ui->boxBS->addItem("2x");connect(this, &MainWindow::speedChanged, _simpleVp, &SimpleVideoPlayer::setPlaybackSpeed);//视频文件路径videoStr["起风了----------买辣椒也用券"] = "D:/QT.music/video/qifengle.mkv";videoStr["平凡之路--------朴树"] = "D:/QT.music/video/pingfanzhilu.mkv";videoStr["带我去找夜生活---------告五人"] = "D:/QT.music/video/yeshenghuo.mkv";videoStr["把回忆拼好给你---------王贰浪"] = "D:/QT.music/video/huiyi.mkv";videoStr["悬溺------------葛东琪"] = "D:/QT.music/video/xuanni.mkv";//音乐文件路径audioStr["起风了----------买辣椒也用券"] = "D:/QT.music/audio/qifengle1.mp3";audioStr["平凡之路--------朴树"] = "D:/QT.music/audio/pingfanzhilu.mp3";audioStr["带我去找夜生活---------告五人"] = "D:/QT.music/audio/yeshenghuo.mp3";audioStr["把回忆拼好给你---------王贰浪"] = "D:/QT.music/audio/huiyi.mp3";audioStr["悬溺------------葛东琪"] = "D:/QT.music/audio/xuanni.mp3";QIcon icon;icon.addFile(tr(":/qrs/4.png"));ui->pauseButton->setIconSize(QSize(120,40));ui->pauseButton->setIcon(icon);
}MainWindow::~MainWindow()
{delete ui;delete _simpleVp;delete player;
}void MainWindow::startPlay()
{//获得当前选择歌曲QString Str = ui->comboBox->currentText();qDebug()<<Str;// 加载音乐文件QString currentAudio = audioStr[Str];// player->setMedia(QUrl::fromLocalFile(currentAudio));//0~100音量范围,默认是100ui->Slider->setValue(50);player->setVolume(50);// 加载视频文件QString currentVideo = videoStr[Str];//_simpleVp->setVideo(currentVideo);/*_simpleAp->setAudio("D:/QT.study/onlinePlay/qifengle1.mp3");开始播放,QThread类的成员函数_simpleAp->start();*///开始播放player->play();_simpleVp->start();}

因为需要里面需要打开的文件位置,所以打开时需要更改位置
在这里插入图片描述

添加功能

我们目前只是完成了打开视频和音频的功能,还需要完善一下功能:

  • 打开文件夹
  • 播放暂停
  • 播放下一首歌曲
  • 开启倍速模式
  • 开启调节音量模式

打开文件夹

void MainWindow::openFileDialog()
{//QString filePath = QFileDialog::getOpenFileName(this, "Open Song", "", "Audio Files (*.mp3 *.wav);;All Files (*)");QString filePath = QFileDialog::getOpenFileName(this, "Open Video", "", "Video Files (*.mp4 *.avi *.mkv *.mov);;All Files (*)");ui->openFilePath->setText(filePath);if (!filePath.isEmpty()){// 这里处理用户选择的歌曲,例如将其传递给播放器等。qDebug() << "Selected song:" << filePath;_simpleVp->setVideo(filePath);QString str;for(auto it = videoStr.begin();it != videoStr.end();it++){if(it->second == filePath){str = it->first;break;}}player->setMedia(QUrl::fromLocalFile(audioStr[str]));}
}

播放暂停

void MainWindow::pauseAudio()
{QIcon icon;if (player->state() == QMediaPlayer::PlayingState) {icon.addFile(tr(":/qrs/3.png"));player->pause();//ui->pauseButton->setText("Play");ui->pauseButton->setIconSize(QSize(120,40));ui->pauseButton->setStyleSheet("background-color: transparent;");ui->pauseButton->setFlat(true);ui->pauseButton->setIcon(icon);} else {icon.addFile(tr(":/qrs/4.png"));player->play();//ui->pauseButton->setText("Pause");ui->pauseButton->setIconSize(QSize(120,40));ui->pauseButton->setStyleSheet("background-color: transparent;");ui->pauseButton->setFlat(true);ui->pauseButton->setIcon(icon);}
}

播放上下一首

void MainWindow::nextVideo() //播放下一首歌曲
{int idx = 0;QString fileStr = ui->openFilePath->text();for(auto it = videoStr.begin();it != videoStr.end();it++){if(it->second == fileStr){break;}idx++;}idx = (idx + 1) % 5;int idx1 = idx;QString videoFile;                 //= (videoStr.begin() + idx)->second;QString audioFile;                 //= (audioStr.begin() + idx)->second;for(auto it = videoStr.begin();it != videoStr.end();it++){if(idx == 0){videoFile = it->second;break;}idx--;}for(auto it = audioStr.begin();it != audioStr.end();it++){if(idx1 == 0){audioFile = it->second;break;}idx1--;}ui->openFilePath->setText(videoFile);_simpleVp->setVideo(videoFile);player->setMedia(QUrl::fromLocalFile(audioFile));_simpleVp->start();player->play();
}//实现上一首歌曲功能
void MainWindow::previousVideo()
{int idx = 0;QString fileStr = ui->openFilePath->text();for(auto it = videoStr.begin();it != videoStr.end();it++){if(it->second == fileStr){break;}idx++;}idx = (idx - 1 + 5) % 5;int idx1 = idx;QString videoFile;                 //= (videoStr.begin() + idx)->second;QString audioFile;                 //= (audioStr.begin() + idx)->second;for(auto it = videoStr.begin();it != videoStr.end();it++){if(idx == 0){videoFile = it->second;break;}idx--;}for(auto it = audioStr.begin();it != audioStr.end();it++){if(idx1 == 0){audioFile = it->second;break;}idx1--;}ui->openFilePath->setText(videoFile);_simpleVp->setVideo(videoFile);player->setMedia(QUrl::fromLocalFile(audioFile));_simpleVp->start();player->play();
}

选择倍速

void MainWindow::onSpeedChanged() //选择不同倍速时,会给视频和音频发射信号
{QString SpeedStr = ui->boxBS->currentText();if(SpeedStr == "2x"){player->setPlaybackRate(2.0);}else if(SpeedStr == "0.5x"){player->setPlaybackRate(0.5);}else {player->setPlaybackRate(1.0);}emit speedChanged(SpeedStr);
}

效果展示

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

项目下载

GitHub下载:
https://github.com/Shy2593666979/onlinePlay

百度网盘下载:
链接:https://pan.baidu.com/s/11NaEgQIrj-Z1FLzbyGcL-w
提取码:0703

歌曲文件下载:
链接:https://pan.baidu.com/s/1qs3CmqWdPT6XrFlY039ULQ
提取码:0703


更多资料尽在 GitHub 欢迎各位读者去Star

⭐学术交流群Q 754410389 持续更新中~~~

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS3背景样式

在CSS 2.1中&#xff0c;background属性的功能还无法满足设计的需求&#xff0c;为了方便设计师更灵活地设计需要的网页效果&#xff0c;CSS3在原有background基础上新增了一些功能属性&#xff0c;可以在同一个对象内叠加多个背景图像&#xff0c;可以改变背景图像的大小尺寸&…

「直播回放」使用 PLC + OPC + TDengine,快速搭建烟草生产监测系统

在烟草工业场景里&#xff0c;多数设备的自动控制都是通过 PLC 可编程逻辑控制器来实现的&#xff0c;PLC 再将采集的数据汇聚至 OPC 服务器。传统的 PI System、实时数据库、组态软件等与 OPC 相连&#xff0c;提供分析、可视化、报警等功能&#xff0c;这类系统存在一些问题&…

判断字符串是否为json

//营业时间返回数组String businessDate merchantInfoResp.getBusinessDate();Object obj JSON.parse(businessDate);if (obj instanceof JSONArray) {merchantInfoResp.setBusinessDateDesc(JSON.parseArray(JSON.toJSONString(obj), Integer.class));} else {//营业日期判断…

最近面试者对接口测试的理解真把我给笑拥了~

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

MySQL 优化思路篇

MySQL 优化思路篇 1、MySQL 查询的优化步骤2、查询系统性能参数3、慢查询日志定位问题3.1、开启慢查询日志参数3.2、查看慢查询数目3.3、慢查询日志的分析工具 mysqldumpslow3.4、关闭慢查询日志3.5、慢查询日志的删除与重建 4、SHOW PROFILE &#xff1a;查看SQL执行成本 1、…

IntelliJ IDEA Services工具栏运行不显示端口问题解决

问题 如Spring Boot服务启动时&#xff0c;端口不显示。 解决 1、 清理所有缓存 2、 关闭IntelliJ IDEA后&#xff0c;到C:\Users\&#xff08;你自己的用户名&#xff09;\AppData\Local\Temp路径把所有文件都删除&#xff0c;因为时一个缓存&#xff0c;不影响其他软件…

智慧灯杆网关智能化选择(网关助力城市完整项目方案)

在当代城市发展中&#xff0c;智慧照明作为一项重要的技术创新&#xff0c;正逐渐改变着我们的城市生活。作为城市智慧照明的核心设备&#xff0c;智慧灯杆网关SG600凭借出色的性能和创新的解决方案&#xff0c;成为了引领城市智慧照明的完美选择。本文将详细介绍SG600的特点和…

Java实现Hive UDF详细步骤 (Hive 3.x版本,IDEA开发)

这里写目录标题 前言1. 新建项目2.配置maven依赖3.编写代码4.打jar包5.上传服务器6.代码中引用 前言 老版本编写UDF时&#xff0c;需要继承 org.apache.hadoop.hive.ql.exec.UDF类&#xff0c;然后直接实现evaluate()方法即可。 由于公司hive版本比较高&#xff08;3.x&#x…

【有源码】基于Python的篮球人才管理系统Springboot的篮球竞赛管理系统(源码、调试、lw、开题报告、ppt)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人七年开发经验&#xff0c;擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等&#xff0c;大家有这一块的问题可以一起交流&#xff01; &#x1f495;&…

Cookie+Session

目录 Cookie和Session 实现模拟登录 1.编写登录页面 2.编写LoginServlet处理登录请求 3.编写indexServlet显示登录页面 Cookie和Session Cookie:浏览器提供的持久化储存数据的机制。把信息保存到客户端&#xff0c;后续访问服务器的时候带着cookie数据进行访问。 服务器通…

2023NOIP A层联测23-涂鸦

有一面由 n m n\times m nm 个格子组成的墙&#xff0c;每个格子要么是黑色&#xff0c;要么是白色。你每次将会进行这样的操作&#xff1a;等概率随机选择一个位置 ( x , y ) (x,y) (x,y)&#xff0c;和一个颜色 c c c&#xff08;黑色或者白色&#xff09;&#xff08; 1…

Redo Log(重做日志)的刷盘策略

1. 概述 Redo Log&#xff08;重做日志&#xff09;是 InnoDB 存储引擎中的一种关键组件&#xff0c;用于保障数据库事务的持久性和崩溃恢复。InnoDB 将事务所做的更改先记录到重做日志&#xff0c;之后再将其应用到磁盘上的数据页。 刷盘策略&#xff08;Flush Policy&#x…

如何记录每天的工作日程?电脑手机通用的日程管理软件

在工作时间有限&#xff0c;但工作任务愈加繁多的现在职场中&#xff0c;要求每一个职场人士做好高效日程管理。通过高效管理日程&#xff0c;我们可以更好地组织和安排任务&#xff0c;合理分配时间和优先级&#xff0c;这有助于我们更专注地进行工作&#xff0c;减少时间的浪…

MCU HardFault_Handler调试方法

一.获取内核寄存器的值 1.在MDK的DEBUG模式下&#xff0c;当程序出现跑飞后&#xff0c;确定卡死在HardFault_Handler中断处 2. 通过Register窗口读取LR寄存器的值来确定当前系统使用堆栈是MSP还是PSP LR寄存器值堆栈寄存器0xFFFFFFF9MSP寄存器0xFFFFFFFDPSP寄存器 如下图所…

【JavaEE】cookie和session

cookie和session cookie什么是 cookieServlet 中使用 cookie相应的API Servlet 中使用 session 相应的 API代码示例: 实现用户登陆Cookie 和 Session 的区别总结 cookie 什么是 cookie cookie的数据从哪里来? 服务器返回给浏览器的 cookie的数据长什么样? cookie 中是键值对…

HR模块开发(1):简单的开发流程和注意事项

HR模块开发 一、模块概述 人力资源管理解决方案关注3个领域:每位雇员都发展和维护着‘公司内’和‘公司外’的种种‘关系’。运用科技,强化这些关系,可以提高忠诚度和生产力,公司整体得到商业价值。 员工关系管理员工职业生命周期管理员工事务处理管理HR模块的基本知识和构…

[Unity][VR]透视开发系列4-解决只看得到Passthrough但看不到Unity对象的问题

【视频资源】 视频讲解地址请关注我的B站。 专栏后期会有一些不公开的高阶实战内容或是更细节的指导内容。 B站地址: https://www.bilibili.com/video/BV1Zg4y1w7fZ/ 我还有一些免费和收费课程在网易云课堂(大徐VR课堂): https://study.163.com/provider/480000002282025/…

算法通关村第四关-黄金挑战基础计算器问题

大家好我是苏麟 , 今天带来栈的比较难的问题 . 计算器问题 基础计算器 LeetCode 224 描述 : 给你一个字符串表达式 s &#xff0c;请你实现一个基本计算器来计算并返回它的值。 s 由数字、、-、(、)、和 组成s 表示一个有效的表达式 不能用作一元运算(例如&#xff0c; …

2014年亚太杯APMCM数学建模大赛A题无人机创造安全环境求解全过程文档及程序

2014年亚太杯APMCM数学建模大赛 A题 无人机创造安全环境 原题再现 20 国集团&#xff0c;又称 G20&#xff0c;是一个国际经济合作论坛。2016 年第 11 届 20 国集团峰会将在中国召开&#xff0c;这是继 APEC 后中国将举办的另一个大型峰会。此类大型峰会&#xff0c;举办城市…

【计算机网络】浏览器的通信能力

1. 用户代理 浏览器可以代替用户完成http请求&#xff0c;代替用户解析响应结果&#xff0c;所以我们称之为用户代理 user agent。 浏览器两大核心能力&#xff1a; 自动发送请求的能力自动解析响应的能力 1.1 自动发送请求的能力 用户在地址栏输入了一个url地址&#xff0…