鸿蒙(API 12 Beta3版)【音视频解封装】 文件解析封装

news2024/11/24 13:07:47

开发者可以调用本模块的Native API接口,完成音视频解封装,即从比特流数据中取出音频、视频等媒体帧数据。

当前支持的数据输入类型有:远程连接(http协议、HLS协议)和文件描述符(fd)。

支持的解封装格式如下:

媒体格式封装格式码流格式
音视频mp4视频码流:AVC(H.264)、HEVC(H.265)音频码流:AAC、MPEG(MP3)、AudioVivid
音视频fmp4视频码流:AVC(H.264)、HEVC(H.265)音频码流:AAC、MPEG(MP3)、AudioVivid
音视频mkv视频码流:AVC(H.264)、HEVC(H.265)音频码流:AAC、MPEG(MP3)、OPUS
音视频mpeg-ts视频码流:AVC(H.264)、HEVC(H.265)音频码流:AAC、MPEG(MP3)、Audio Vivid
音视频flv视频码流:AVC(H.264)、HEVC(H.265)音频码流:AAC
音频m4a音频码流:AAC、AudioVivid
音频aac音频码流:AAC
音频mp3音频码流:MPEG(MP3)
音频ogg音频码流:OGG
音频flac音频码流:FLAC
音频wav音频码流:PCM
音频amr音频码流:AMR(AMR-NB、AMR-WB)
音频ape音频码流:APE
外挂字幕srt字幕流:SRT

适用场景

  • 播放

    播放媒体文件时,需要先对音视频流进行解封装,然后使用解封装获取的帧数据进行解码和播放。

  • 音视频编辑

    编辑媒体文件时,需要先对音视频流进行解封装,获取到指定帧进行编辑。

  • 媒体文件格式转换(转封装)

    媒体文件格式转换时,需要先对音视频流进行解封装,然后按需将音视频流封装至新的格式文件内。

开发指导

说明

  • 调用解封装能力解析网络播放路径,需要[声明权限]:ohos.permission.INTERNET
  • 调用解封装能力解析本地文件,需要[向用户申请授权]:ohos.permission.READ_MEDIA
  • 如果使用ResourceManager.getRawFd打开HAP资源文件描述符,使用方法请参考[ResourceManager API参考]

在 CMake 脚本中链接动态库

target_link_libraries(sample PUBLIC libnative_media_codecbase.so)
target_link_libraries(sample PUBLIC libnative_media_avdemuxer.so)
target_link_libraries(sample PUBLIC libnative_media_avsource.so)
target_link_libraries(sample PUBLIC libnative_media_core.so)

开发步骤

  1. 添加头文件。
#include <multimedia/player_framework/native_avdemuxer.h>
#include <multimedia/player_framework/native_avsource.h>
#include <multimedia/player_framework/native_avcodec_base.h>
#include <multimedia/player_framework/native_avformat.h>
#include <multimedia/player_framework/native_avbuffer.h>
#include <fcntl.h>
#include <sys/stat.h>
  1. 创建资源管理实例对象。
// 创建文件操作符 fd,打开时对文件句柄必须有读权限(filePath 为待解封装文件路径,需预置文件,保证路径指向的文件存在)
std::string filePath = "test.mp4";
int fd = open(filePath.c_str(), O_RDONLY);
struct stat fileStatus {};
size_t fileSize = 0;
if (stat(filePath.c_str(), &fileStatus) == 0) {
   fileSize = static_cast<size_t>(fileStatus.st_size);
} else {
   printf("get stat failed");
   return;
}
// 为 fd 资源文件创建 source 资源对象, 传入 offset 不为文件起始位置 或 size 不为文件大小时,可能会因不能获取完整数据导致 source 创建失败、或后续解封装失败等问题
OH_AVSource *source = OH_AVSource_CreateWithFD(fd, 0, fileSize);
if (source == nullptr) {
   printf("create source failed");
   return;
}
// 为 uri 资源文件创建 source 资源对象(可选)
// OH_AVSource *source = OH_AVSource_CreateWithURI(uri);

// 为自定义数据源创建 source 资源对象(可选)。使用该方式前,需要先实现AVSourceReadAt接口函数实现。
// 当使用OH_AVSource_CreateWithDataSource时需要补充g_filePath
// g_filePath = filePath ;
// OH_AVDataSource dataSource = {fileSize, AVSourceReadAt};
// OH_AVSource *source = OH_AVSource_CreateWithDataSource(&dataSource);

AVSourceReadAt接口函数,需要放在创建资源管理实例对象前实现::

// 添加头文件
#include <fstream>
static std::string g_filePath;

enum MediaDataSourceError : int32_t {
   SOURCE_ERROR_IO = -2,
   SOURCE_ERROR_EOF = -1
};

int32_t AVSourceReadAt(OH_AVBuffer *data, int32_t length, int64_t pos)
{
   if (data == nullptr) {
      printf("AVSourceReadAt : data is nullptr!\n");
      return MediaDataSourceError::SOURCE_ERROR_IO;
   }

   std::ifstream infile(g_filePath, std::ofstream::binary);
   if (!infile.is_open()) {
      printf("AVSourceReadAt : open file failed! file:%s\n", g_filePath.c_str());
      return MediaDataSourceError::SOURCE_ERROR_IO;  // 打开文件失败
   }

   infile.seekg(0, std::ios::end);
   int64_t fileSize = infile.tellg();
   if (pos >= fileSize) {
      printf("AVSourceReadAt : pos over or equals file size!\n");
      return MediaDataSourceError::SOURCE_ERROR_EOF;  // pos已经是文件末尾位置,无法读取
   }

   if (pos + length > fileSize) {
      length = fileSize - pos;    // pos+length长度超过文件大小时,读取从pos到文件末尾的数据
   }

   infile.seekg(pos, std::ios::beg);
   if (length <= 0) {
      printf("AVSourceReadAt : raed length less than zero!\n");
      return MediaDataSourceError::SOURCE_ERROR_IO;
   }
   char* buffer = new char[length];
   infile.read(buffer, length);
   infile.close();

   memcpy(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(data)),
      buffer, length);
   delete[] buffer;

   return length;
}
  1. 创建解封装器实例对象。
// 为资源对象创建对应的解封装器
OH_AVDemuxer *demuxer = OH_AVDemuxer_CreateWithSource(source);
if (demuxer == nullptr) {
   printf("create demuxer failed");
   return;
}
  1. 注册[DRM信息监听函数](可选,若非DRM码流或已获得[DRM信息],可跳过此步)。

添加头文件

#include <multimedia/drm_framework/native_drm_common.h>

在 CMake 脚本中链接动态库

target_link_libraries(sample PUBLIC libnative_drm.so)

设置DRM信息监听的接口有两种,可根据需要选择。

使用示例一:

// DRM信息监听回调OnDrmInfoChanged实现
static void OnDrmInfoChanged(DRM_MediaKeySystemInfo *drmInfo)
{
   // 解析DRM信息,包括数量、DRM类型及对应pssh
}

DRM_MediaKeySystemInfoCallback callback = &OnDrmInfoChanged;
Drm_ErrCode ret = OH_AVDemuxer_SetMediaKeySystemInfoCallback(demuxer, callback);

使用示例二:

// DRM信息监听回调OnDrmInfoChangedWithObj实现
static void OnDrmInfoChangedWithObj(OH_AVDemuxer *demuxer, DRM_MediaKeySystemInfo *drmInfo)
{
   // 解析DRM信息,包括数量、DRM类型及对应pssh
}

Demuxer_MediaKeySystemInfoCallback callback = &OnDrmInfoChangedWithObj;
Drm_ErrCode ret = OH_AVDemuxer_SetDemuxerMediaKeySystemInfoCallback(demuxer, callback);

在监听到DRM信息后,也可主动调用获取DRM信息(uuid及对应pssh)接口。

DRM_MediaKeySystemInfo mediaKeySystemInfo;
OH_AVDemuxer_GetMediaKeySystemInfo(demuxer, &mediaKeySystemInfo);
  1. 获取文件轨道数(可选,若用户已知轨道信息,可跳过此步)。
// 从文件 source 信息获取文件轨道数,用户可通过该接口获取文件级别属性,具体支持信息参考附表 1
OH_AVFormat *sourceFormat = OH_AVSource_GetSourceFormat(source);
if (sourceFormat == nullptr) {
   printf("get source format failed");
   return;
}
int32_t trackCount = 0;
if (!OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &trackCount)) {
   printf("get track count from source format failed");
   return;
}
OH_AVFormat_Destroy(sourceFormat);
  1. 获取轨道index及信息(可选,若用户已知轨道信息,可跳过此步)。
uint32_t audioTrackIndex = 0;
uint32_t videoTrackIndex = 0;
int32_t w = 0;
int32_t h = 0;
int32_t trackType;
for (uint32_t index = 0; index < (static_cast<uint32_t>(trackCount)); index++) {
   // 获取轨道信息,用户可通过该接口获取对应轨道级别属性,具体支持信息参考附表 2
   OH_AVFormat *trackFormat = OH_AVSource_GetTrackFormat(source, index);
   if (trackFormat == nullptr) {
      printf("get track format failed");
      return;
   }
   if (!OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType)) {
      printf("get track type from track format failed");
      return;
   }
   static_cast<OH_MediaType>(trackType) == OH_MediaType::MEDIA_TYPE_AUD ? audioTrackIndex = index : videoTrackIndex = index;
   // 获取视频轨宽高
   if (trackType == OH_MediaType::MEDIA_TYPE_VID) {
      if (!OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_WIDTH, &w)) {
         printf("get track width from track format failed");
         return;
      }
      if (!OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_HEIGHT, &h)) {
         printf("get track height from track format failed");
         return;
      }
   }
   OH_AVFormat_Destroy(trackFormat);
}
  1. 添加解封装轨道。
if(OH_AVDemuxer_SelectTrackByID(demuxer, audioTrackIndex) != AV_ERR_OK){
   printf("select audio track failed: %d", audioTrackIndex);
   return;
}
if(OH_AVDemuxer_SelectTrackByID(demuxer, videoTrackIndex) != AV_ERR_OK){
   printf("select video track failed: %d", videoTrackIndex);
   return;
}
// 取消选择轨道(可选)
// OH_AVDemuxer_UnselectTrackByID(demuxer, audioTrackIndex);
  1. 调整轨道到指定时间点(可选)。
// 调整轨道到指定时间点,后续从该时间点进行解封装
// 注意:
// 1. mpegts格式文件使用OH_AVDemuxer_SeekToTime功能时,跳转到的位置可能为非关键帧。可在跳转后调用OH_AVDemuxer_ReadSampleBuffer,通过获取到的OH_AVCodecBufferAttr判断当前帧是否为关键帧。若非关键帧影响应用侧显示等功能,可在跳转后循环读取,获取到后续第一帧关键帧后,再进行解码等处理。
// 2. ogg格式文件使用OH_AVDemuxer_SeekToTime功能时,会跳转到传入时间millisecond所在时间间隔(秒)的起始处,可能会导致一定数量的帧误差。
OH_AVDemuxer_SeekToTime(demuxer, 0, OH_AVSeekMode::SEEK_MODE_CLOSEST_SYNC);
  1. 开始解封装,循环获取帧数据(以含音频、视频两轨的文件为例)。
// 创建 buffer,用与保存用户解封装得到的数据
OH_AVBuffer *buffer = OH_AVBuffer_Create(w * h * 3 >> 1);
if (buffer == nullptr) {
   printf("build buffer failed");
   return;
}
OH_AVCodecBufferAttr info;
bool videoIsEnd = false;
bool audioIsEnd = false;
int32_t ret;
while (!audioIsEnd || !videoIsEnd) {
   // 在调用 OH_AVDemuxer_ReadSampleBuffer 接口获取数据前,需要先调用 OH_AVDemuxer_SelectTrackByID 选中需要获取数据的轨道
   // 获取音频帧数据
   if(!audioIsEnd) {
      ret = OH_AVDemuxer_ReadSampleBuffer(demuxer, audioTrackIndex, buffer);
      if (ret == AV_ERR_OK) {
         // 可通过 buffer 获取并处理音频帧数据
         OH_AVBuffer_GetBufferAttr(buffer, &info);
         printf("audio info.size: %d\n", info.size);
         if (info.flags == OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS) {
            audioIsEnd = true;
         }
      }
   }
   if(!videoIsEnd) {
      ret = OH_AVDemuxer_ReadSampleBuffer(demuxer, videoTrackIndex, buffer);
      if (ret == AV_ERR_OK) {
         // 可通过 buffer 获取并处理视频帧数据
         OH_AVBuffer_GetBufferAttr(buffer, &info);
         printf("video info.size: %d\n", info.size);
         if (info.flags == OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS) {
            videoIsEnd = true;
         }
      }
   }
}
OH_AVBuffer_Destroy(buffer);
  1. 销毁解封装实例。
// 需要用户调用 OH_AVSource_Destroy 接口成功后,手动将对象置为 NULL,对同一对象重复调用 OH_AVSource_Destroy 会导致程序错误
if (OH_AVSource_Destroy(source) != AV_ERR_OK) {
   printf("destroy source pointer error");
}
source = NULL;
// 需要用户调用 OH_AVDemuxer_Destroy 接口成功后,手动将对象置为 NULL,对同一对象重复调用 OH_AVDemuxer_Destroy 会导致程序错误
if (OH_AVDemuxer_Destroy(demuxer) != AV_ERR_OK) {
   printf("destroy demuxer pointer error");
}
demuxer = NULL;
close(fd);

附表

文件级别属性支持范围

说明

正常解析时才可以获取对应属性数据;如果文件信息错误或缺失,将导致解析异常,无法获取数据。

表1 文件级别属性支持范围

名称描述
OH_MD_KEY_TITLE文件标题的键
OH_MD_KEY_ARTIST文件艺术家的键
OH_MD_KEY_ALBUM文件专辑的键
OH_MD_KEY_ALBUM_ARTIST文件专辑艺术家的键
OH_MD_KEY_DATE文件日期的键
OH_MD_KEY_COMMENT文件注释的键
OH_MD_KEY_GENRE文件流派的键
OH_MD_KEY_COPYRIGHT文件版权的键
OH_MD_KEY_LANGUAGE文件语言的键
OH_MD_KEY_DESCRIPTION文件描述的键
OH_MD_KEY_LYRICS文件歌词的键
OH_MD_KEY_TRACK_COUNT文件轨道数量的键
OH_MD_KEY_DURATION文件时长的键
OH_MD_KEY_START_TIME文件起始时间的键

轨道级别属性支持范围

说明

正常解析时才可以获取对应属性数据;如果文件信息错误或缺失,将导致解析异常,无法获取数据。

表2 轨道级别属性支持范围

名称描述视频轨支持音频轨支持字幕轨支持
OH_MD_KEY_CODEC_MIME码流编解码器类型的键
OH_MD_KEY_TRACK_TYPE码流媒体类型的键
OH_MD_KEY_BITRATE码流比特率的键-
OH_MD_KEY_LANGUAGE码流语言类型的键-
OH_MD_KEY_CODEC_CONFIG编解码器特定数据的键,视频中表示传递xps,音频中表示传递extraData-
OH_MD_KEY_WIDTH视频流宽度的键--
OH_MD_KEY_HEIGHT视频流高度的键--
OH_MD_KEY_FRAME_RATE视频流帧率的键--
OH_MD_KEY_ROTATION视频流旋转角度的键--
OH_MD_KEY_VIDEO_SAR视频流样本长宽比的键--
OH_MD_KEY_PROFILE视频流编码档次,只针对 h265 码流使用--
OH_MD_KEY_RANGE_FLAG视频流视频YUV值域标志的键,只针对 h265 码流使用--
OH_MD_KEY_COLOR_PRIMARIES视频流视频色域的键,只针对 h265 码流使用--
OH_MD_KEY_TRANSFER_CHARACTERISTICS视频流视频传递函数的键,只针对 h265 码流使用--
OH_MD_KEY_MATRIX_COEFFICIENTS视频矩阵系数的键,只针对 h265 码流使用--
OH_MD_KEY_VIDEO_IS_HDR_VIVID视频流标记是否为 HDRVivid 的键,只针对 HDRVivid 码流使用--
OH_MD_KEY_AUD_SAMPLE_RATE音频流采样率的键--
OH_MD_KEY_AUD_CHANNEL_COUNT音频流通道数的键--
OH_MD_KEY_CHANNEL_LAYOUT音频流所需编码通道布局的键--
OH_MD_KEY_AUDIO_SAMPLE_FORMAT音频流样本格式的键--
OH_MD_KEY_AAC_IS_ADTSaac格式的键,只针对 aac 码流使用--
OH_MD_KEY_BITS_PER_CODED_SAMPLE音频流每个编码样本位数的键--

最后呢

很多开发朋友不知道需要学习那些鸿蒙技术?鸿蒙开发岗位需要掌握那些核心技术点?为此鸿蒙的开发学习必须要系统性的进行。

而网上有关鸿蒙的开发资料非常的少,假如你想学好鸿蒙的应用开发与系统底层开发。你可以参考这份资料,少走很多弯路,节省没必要的麻烦。由两位前阿里高级研发工程师联合打造的《鸿蒙NEXT星河版OpenHarmony开发文档》里面内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(Harmony NEXT)技术知识点

如果你是一名Android、Java、前端等等开发人员,想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。下面是鸿蒙开发的学习路线图。

在这里插入图片描述

针对鸿蒙成长路线打造的鸿蒙学习文档。话不多说,我们直接看详细鸿蒙(OpenHarmony )手册(共计1236页)与鸿蒙(OpenHarmony )开发入门视频,帮助大家在技术的道路上更进一步。

  • 《鸿蒙 (OpenHarmony)开发学习视频》
  • 《鸿蒙生态应用开发V2.0白皮书》
  • 《鸿蒙 (OpenHarmony)开发基础到实战手册》
  • OpenHarmony北向、南向开发环境搭建
  • 《鸿蒙开发基础》
  • 《鸿蒙开发进阶》
  • 《鸿蒙开发实战》

在这里插入图片描述

总结

鸿蒙—作为国家主力推送的国产操作系统。部分的高校已经取消了安卓课程,从而开设鸿蒙课程;企业纷纷跟进启动了鸿蒙研发。

并且鸿蒙是完全具备无与伦比的机遇和潜力的;预计到年底将有 5,000 款的应用完成原生鸿蒙开发,未来将会支持 50 万款的应用。那么这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行! 自↓↓↓拿

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

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

相关文章

高效修复,2024年SD卡损坏数据恢复利器推荐

如果你也是爱记录生活的小伙伴外出游玩的时候肯定会带上带你的长枪短炮吧。如果预算充足可以直接考虑双盘位的设备&#xff0c;为你的图片上个保险。如果是单卡槽的设备回来的时候发现照片全无了咋办&#xff0c;这次我们就探讨下sd卡数据恢复要怎么进行吧。 1.福昕恢复数据 …

【递归】3.反转链表

leetcode题目连接&#xff1a;https://leetcode.cn/problems/reverse-linked-list/题解过程&#xff1a; 1.找到重复的子问题 要逆序第一个节点&#xff0c;就把后面的节点都逆序一遍 2.关注到具体的子问题的实现 第一步&#xff1a;将当前节点的后面所有节点逆置 第二步&…

【自动驾驶】ROS中自定义格式的服务通信,含命令行动态传参(c++)

目录 通信流程创建服务器端及客户端新建服务通讯文件修改service的xml及cmakelistCMakeLists.txt编辑 msg 相关配置编译消息相关头文件在cmakelist中包含头文件的路径在service包下编写service.cpp在client包下编写client.cpp测试运行查询服务的相关指令列出目前的所有服务&…

毛骨悚然,ChatGPT诡异尖叫、模仿用户说话,GPT-4o被曝行为失控

ChatGPT被曝存在失控行为&#xff0c;原本是用户和ChatGPT正常的语音对话&#xff0c;但ChatGPT却突然大喊了一声“no”&#xff0c;随即竟模仿起了用户的声音&#xff01; 下面就是这段让人毛骨悚然的声音片段&#xff1a; ChatGPT失控行为首次公开很多网友表示&#xff0c;第…

【MySQL】2.MySQL实际操作

目录 一、数据分析基本流程 注&#xff1a;Navicat快捷键 二、获取数据后的代码操作 &#xff08;1&#xff09;探索数据&#xff0c;查看定义 &#xff08;2&#xff09;筛选有用的字段 &#xff08;3&#xff09;建新表&#xff08;查询建表插值 三合一&#xff09; 注意…

揭秘Java 8新宠儿:初识Optional,让你的代码告别空指针烦恼

文章目录 前言一、Optional基础二、使用步骤1.创建Optional实例1.常用方法 前言 Java 8 引入了一个非常有用的类 Optional&#xff0c;它旨在减少空指针异常&#xff08;NullPointerException&#xff09;的发生。Optional 类是一个可以包含也可以不包含非null值的容器对象。如…

20240813在荣品RK3588S-AHD开发板的预置Android13中挂载ext4格式的256GB的TF卡

df -h mount fdisk无效 20240813在荣品RK3588S-AHD开发板的预置Android13中挂载ext4格式的256GB的TF卡 2024/8/13 11:24 缘起&#xff1a;当时比较便宜96.9&#xffe5;/想看看256GB的TF卡的高速卡的效果&#xff0c;就在京东入手了3张三星的高速TF卡。最近在弄RK3588S&#xf…

4款AI自动生成PPT神器,制作PPT太容易了

在当今数字化时代&#xff0c;无论是职场人士还是在校学生&#xff0c;PPT已经成为工作和学习中不可或缺的展示工具。从项目回顾到学术答辩&#xff0c;甚至是婚礼致辞&#xff0c;一份精心制作的PPT总能给人留下深刻印象。 为了帮助您更高效地完成PPT制作&#xff0c;我们将介…

数据科学、数据分析、人工智能必备知识汇总-----常用数据分析方法-----持续更新

数据科学、数据分析、人工智能必备知识汇总-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/140174015 文章目录 一、对比分析法1. 按时间和地区2. 同比和环比 二、分组分析法三、结构分析法四、交叉分析法五、矩阵分…

【话题】AI时代的程序员:挑战、机遇与核心竞争力的重塑

目录 人工智能时代&#xff0c;程序员如何保持核心竞争力&#xff1f; ​编辑引言 方向一&#xff1a;AI辅助编程对程序员工作的影响 案例 潜在的风险与对策 方向二&#xff1a;程序员应重点发展的核心能力 核心竞争力 如何培养这些能力 方向三&#xff1a;人机协作模式下的职业…

图论------贝尔曼-福德(Bellman-Ford)算法

算法概述&#xff1a; Bellman-Ford算法核心代码如下 for(int i 1;i<n-1;i) for(int j 1;j<m;j) if(dic[v[j]]> dic[u[j]] w[j]] dic[v[j]] dic[u[j]] w[j]; 首先我们要了解一个点就是我们这次不再使用邻接矩阵来存储图的信息&#xff0c;而是定义三个一维数组来…

Kubernetes之pod的污点和容忍度

污点和容忍度 污点&#xff08;Taint&#xff09;&#xff0c;它使节点能够排斥一类特定的 Pod。 容忍度&#xff08;Toleration&#xff09; 是应用于 Pod 上的&#xff0c;容忍度允许调度器调度带有对应污点的 Pod。 容忍度允许调度但并不保证调度&#xff1a;作为其功能的…

构建即时通讯应用:Spring boot高效集成WebSocket、Stomp协议完成前后端持续通信

1. 引入依赖 在你的Spring Boot项目的pom.xml中添加以下依赖&#xff1a; <dependencies><!-- Spring Boot Starter Thymeleaf --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf&…

黑龙江日报报道第5届中国计算机应用技术大赛,赛氪提供赛事支持

2024年7月17日&#xff0c;黑龙江日报、极光新闻对在哈尔滨市举办的第5届中国计算机应用技术大赛全国总决赛进行了深入报道。此次大赛由中国计算机学会主办&#xff0c;中国计算机学会计算机应用专业委员会与赛氪网共同承办&#xff0c;吸引了来自全国各地的顶尖技术团队和选手…

振德医疗选择泛微千里聆RPA,助力电商、人事业务流程自动化

振德医疗用品股份有限公司成立于1994年&#xff0c;中国A股上市公司&#xff0c;是医用敷料和感控防护产品主要的供应商之一。 &#xff08;图片素材来自振德医疗官网&#xff09; 振德医疗的业务在线上线下齐发力。目前拥有5个国内生产基地&#xff0c;3个海外工厂&#xff0…

算法分析报告:商江小智文本生成算法

1. 算法全周期分析 算法安全与监测 信息内容安全&#xff1a;算法通过预处理和特征提取确保输入数据的安全&#xff0c;避免敏感信息泄露。信息源安全&#xff1a;算法依赖于训练数据集&#xff0c;需确保数据来源的合法性和隐私保护。信息安全监测&#xff1a;算法应实时监控…

(回溯) LeetCode 17. 电话号码的组合

原题链接 一. 题目描述 17. 电话号码的字母组合 已解答 中等 相关标签 相关企业 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对…

Linux 下 ETCD 安装、配置与命令使用总结

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; Linux 下 ETCD 安装、配置与命令使用总结 ETCD 是一个分布式键值存储系统&#xff0c;广泛用于服务发现、分布式锁、配置管理等场景&#xff0c;特别是在 Kubernetes 集群中发挥着至关重要的作用。ETCD 的高…

LoRA实现大模型LLM微调研究

LoRA&#xff0c;即低秩适应&#xff08;Low-Rank Adaptation&#xff09;&#xff0c;作为一种创新的微调方法&#xff0c;为大模型的优化与定制提供了一条高效、节省资源的新途径。 在快速发展的AI时代背景下&#xff0c;大型语言模型因其卓越的性能和广泛的应用前景&#xf…

(限时免费)震惊!流落人间的haproxy宝典被找到了!一切玄妙尽在此处!

目录 haproxy七层代理详解一、负载均衡1.1 什么是负载均衡1.2 为什么使用负载均衡1.3 负载均衡类型1.3.1 硬件负载1.3.2 四层负载1.3.3 七层负载1.3.4 四层与七层的区别 二、haproxy介绍2.1 haproxy简介2.2 haproxy特性 三、haproxy详细部署3.1 实验所用的环境3.2 软件安装3.3 …