当前位置: 首页 > news >正文

阿里云迁移AWS视频点播技术攻坚

文章目录

  • 🐷 背景
  • 🦥 简述
  • 🐥 Aws服务
  • 🦜 AWS CloudFormation
  • 🐞 问题
  • 🐉 落地方案
  • 🦉 Aws vs Aliyun
  • 🍄 避坑指南

🐷 背景

由于AWS整体成本略低于阿里云,公司决定将文件存储模块的业务迁移至AWS,迁移过程中发现,关于视频播放,转码之前阿里云已自动集成相关功能,但Aws并没有原生支持,为此踩了很多坑!

🦥 简述

本次主要是完成视频上传Aws并完成转码播放功能,基础功能已实现,但速度方面略低于阿里云,后续还需要优化改进。

Aws指南

🐥 Aws服务

  • Amazon Elemental MediaConvert 将媒体文件从源格式转码为可在智能手机、平板电 脑、PC 和其他设备播放的流媒体格式。
  • Amazon CloudFront 加速将您的视频内容分发给最终用户。
  • Amazon Step Functions 讲执行不同任务的离散函数整合为工作流。
  • Amazon Lambda 让您无需预置或管理服务器即可运行代码。
  • Amazon Simple Storage Service (Amazon S3) 用于对象存储。
  • Amazon DynamoDB 用于追踪源和目标文件的元数据以及工作流程的进度。
  • Amazon CloudWatch 用于追踪转码任务。
  • Amazon Simple Queue Service (Amazon SQS) 用于捕获工作流的输出。
  • Amazon Simple Notification Service (Amazon SNS) 用于发送发布、编码和错误的通知信息。

按照aws解决方案库提供的方案,部署大概需要20分钟,部署完成后怎么使用,部署过程都做了哪些事情,整体流程是怎么样的,从哪些环节可以接入自定义的逻辑和程序。
除了以上部署方案提到的服务,本身该部署方案也是一个服务AWS CloudFormation。
根据本次部署和开发经历,建议需要使用该解决方案的小伙伴不要着急部署,先通过各种学习途径了解以上服务,尤其是标红的服务是做什么的,什么应用场景下使用。

B站学习资料:AWS认证解决方案全栈架构师 中文课程

🦜 AWS CloudFormation


CloudFormation是一个模板,该模板包含一套解决方案所需的所有资源,将一个通用解决方案配置成一个模板,需要再次部署相同解决方案则使用模板即可快速实现复制。启动堆栈可对模板进行部署实施。

堆栈部署完成,删除堆栈可将堆栈相关的所有资源进行一并删除,想部署或尝试的可以放心实施,不用删除即可!

Aws点播使用的模板


整体转码流程

官方服务说明


堆栈部署产生的aws服务说明


mediaconvert作业模板


Lambda

Lambda很重要!Lambda很重要!Lambda很重要!


IAM Role

IAM很重要!IAM很重要!IAM很重要!

SQS

SQS消息队列,转码完成后会向消息队列写入消息,业务侧可读取消息实现转码完成事件通知。

🐞 问题

使用Workflow trigger选项VideoFile的话,部署的方案会默认转码成m3u8文件;会默认使用3个模板进行转码(MediaConvert_Template_2160p、MediaConvert_Template_1080p、MediaConvert_Template_720p)于现有阿里云转码成单个mp4文件不一致,现有业务对多种品质输出没有要求,需要能够定制转码输出格式。

备注:如要实现类似点播清晰度选择的话可考虑多个质量转码模板。
解决方案在github上

🐉 落地方案

调整堆栈参数

Workflow trigger选择MetadataFile ,工作流触发参数由VideoFile调整为Metadata,堆栈会进行自动调整。
调整后s3桶事件通知中由之前的视频文件触发工作流,变更为由metadata触发,metadata就是.json的一个文件,具体内容参考github

Metadata文件创建

堆栈调整后,上传视频文件不再触发工作流,此时需要对上传的视频文件生成对应的metadata文件(.json文件),可以由业务侧进行两次上传,先上传视频文件,再上传metadata文件,进而触发工作流。考虑存在失败的可能以及业务侧需要实现额外的逻辑,因此使用了Lambda创建Metadata文件,文件上传完成触发Lambda,由Lambda实现生成Metadata文件。

const aws = require('aws-sdk');const s3 = new aws.S3({ apiVersion: '2006-03-01' });exports.handler = async (event, context) => {// Get the object from the event and show its content typeconst bucket = event.Records[0].s3.bucket.name;const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));if(key.endsWith('.json')){console.log('json file');return;}const params = {Bucket: bucket,Key: key,}; console.log(params);const metadata={"srcVideo": key,"ArchiveSource": true,"FrameCapture":true,"JobTemplate":"jiaoyubaoCompanyVideo_trans_template"};const metadataKey=key.substring(0,key.lastIndexOf('.'))+'.json';console.log('metadatakey:',metadataKey);try {//const { ContentType } = await s3.headObject(params).promise();//console.log('CONTENT TYPE:', ContentType);//upload metadataconst uploadParams = {Bucket: bucket, Key: metadataKey, Body: JSON.stringify(metadata)};console.log(uploadParams);// call S3 to retrieve upload file to specified bucketconst res=await s3.upload (uploadParams).promise();return res;} catch (err) {console.log(err);throw err;}
};

自定义转码模板

默认模板转码为m3u8格式文件,需要实现mp4格式转码,自定义转码模板jiaoyubaoCompanyVideo_trans_template

质量优化级别建议使用单一传递 HQ,太低转码文件质量较低,但文件大小会降低明显,考虑效果,采用中间质量。
最大比特率(位/秒)设置为了2000000,该值会影响转码视频大小,实际测试2000000转码视频较源视频大小略有压缩,固采用该值,如需高质量可参考该值设置更大的值,如需更多的压缩,可降低该值。

完成以上三部,即可通过aws控制台上传视频,触发转码工作流,输出转码视频了

业务侧上传视频

机构后台限制了视频大小50M,考虑到后台上传会导致占用更多的流量,和服务器资源,因此使用客户端直传方案。
使用jssdk实现web直传。

客户端直连S3实现分片续传思路与实践

https://aws.amazon.com/cn/blogs/china/s3-multipul-upload-practice/

授权方案

方案一:STS临时授权

由于客户端直传,使用长久AK(AwsAccessKeyId、AwsSecretAccessKey)的话会造成敏感信息泄漏,存在安全隐患。
临时授权需要一个Role(角色)用于创建一个临时的凭证,前端使用临时凭证上传s3。
为了安全考虑,该角色拥有可用的最小权限,角色绑定策略实现权限限制。因此需要先创建一个策略,然后绑定到该角色。

策略:ClientUploadVideoS3Policy

{"Version": "2012-10-17","Statement": [{"Sid": "VisualEditor0","Effect": "Allow","Action": ["s3:PutObject","s3:GetObject"],"Resource": "arn:aws-cn:s3:::videoondemand-company-source234242b7/*"}]
}

角色:ClientVideoUploadAssumeRole


AssumeRole

private Amazon.SecurityToken.Model.AssumeRoleResponse GetOriginalAwsAssumeRole(int durationSeconds=3600)
{//Amazon Resource Namevar roleArnToAssume = "arn:aws-cn:iam::77480923422862:role/ClientVideoUploadAssumeRole";var client = new Amazon.SecurityToken.AmazonSecurityTokenServiceClient(AWSCredentialsConfig.AwsAccessKeyId,AWSCredentialsConfig.AwsSecretAccessKey,Amazon.RegionEndpoint.CNNorthWest1);// Create the request to use with the AssumeRoleAsync call.var assumeRoleReq = new Amazon.SecurityToken.Model.AssumeRoleRequest(){DurationSeconds = durationSeconds,RoleSessionName = "AwsUpload",RoleArn = roleArnToAssume};var assumeRoleRes =  client.AssumeRole(assumeRoleReq);return assumeRoleRes;
}
{"AssumedRoleUser": {"Arn": "arn:aws-cn:sts::77421422862:assumed-role/ClientVideoUploadAssumeRole/AwsUpload","AssumedRoleId": "AROA3IZSCNY432ZRBYTQU5:AwsUpload"},"Credentials": {"AccessKeyId": "ASIA3234fsdfwe42Q3UK6","Expiration": "2022-12-30T15:24:37+08:00","SecretAccessKey": "khoROTW8vyDSD7tcaDmvMZg7S0Ujte6TiRP+ql2b","SessionToken": "IQoJb3JpZ2luX2VjEGEaDmNuLW5vcnRod2VzdC0xIkYwRAIgUZ7b3+OGVn+agrp3IJ+JRQDjTTgKcGW+F92eOi0CsMICICqooZD6FJoCnOdBNaAPfrvzB5iG4fxzSQL234234uEKp8CCI///wEQABoMNzc0ODA5NzQyODYyIgw+fkUE58kq72ukAWkq8wEbHoeO5inZTKxAr/kafYBQ5RFOyYx8EJjrYd/uCReS6Te/Ix64D9/aqSM/BimyACmnjM3BmeDuys12zYDdHLfOAhuOUR4dyjKEXPWTwV6usxVb+5EYw4T9Z47dX9gV8EoI0n342342jzKnY8iQIikpidsYFjo6g27Q/dddCUXGqhIUB0QtzAhoMRAM9ndVl9w2VH7CBUsFPFXPhUaxhhIol59p8L2342342BKkFFpY/Zf8wSMLBYLLO3p9/uCBA4D06chibtYVoiIPLoMvPDlOEU6iAk+LtKTOtdmZ5/J8+WTGeZB8Y6R7II14wpe++rAY6ngGPSJw/q0JoPm8WMMH84c3Lv47V9n9sDTSX8WHlASPvgySRiuP+DvSd3RqMDootuk3awg1x3hvzU438xJ+BCo5qAWFIJE2niwyslWh3zrxiGADBAqqg/XT2P4yQg8wiscQh38KxSOlj+LxgvTcdVfe4/Yy4uWtudvWR4EkcVvpWWIw+sxDkX0LlYvfHz3yhAq209Gt8E5zcX4NWQ8mnug=="},"PackedPolicySize": 0,"SourceIdentity": null,"ResponseMetadata": {"RequestId": "15c423624-923f4-452b-902e-1e8561175523","Metadata": {},"ChecksumAlgorithm": 0,"ChecksumValidationStatus": 0},"ContentLength": 1463,"HttpStatusCode": 200
}

方案二:使用预签名 URL(未验证)

https://docs.amazonaws.cn/AmazonS3/latest/userguide/using-presigned-url.html

jssdk直传

<script src="/js/aws-sdk-2.45.0.min.js"></script><script>var accessKeyId = "{$:token.Credentials.AccessKeyId}";var accessKeySecret = "{$:token.Credentials.SecretAccessKey}";var sessionToken = "{$:token.Credentials.SessionToken}";var endpoint = `${location.protocol}//s3.cn-northwest-1.amazonaws.com.cn`;var s3 = new AWS.S3({ accessKeyId: accessKeyId, secretAccessKey: accessKeySecret, sessionToken: sessionToken, region: 'cn-northwest-1', endpoint: endpoint, signatureVersion: 'v4' });var filePicker = document.getElementById("videoPicker");var progress = document.getElementById("progress");filePicker.addEventListener('change', function (event) {console.log(event.target.files[0]);if (event.target.files[0].size / 1024 / 1024 > 50) {alert("文件超出大小限制,不得超过50M");document.getElementById("videoPicker").value = null;return;}});function start() {if (filePicker.files.length <= 0) {alert("请先选择视频");return;}var file = filePicker.files[0];var ext = file.name.substring(file.name.lastIndexOf('.'));$("#progressInfo").css({ width: '100%' });filePicker.setAttribute("disabled", "disabled");var params = {Bucket: 'videoondemand-company-source-gbwnqmc885b7',Key: `{$:companyInfo.comid}_${Date.now()}${ext}`,Body:file};var upload = s3.upload(params, {queueSize: 1,//分片上传并发队列,代表了能同时上传的分片数量connectTimeout: 60 * 1000 * 10,httpOptions: {timeout: 60 * 1000 * 10}}).on('httpUploadProgress', function (e) {var percent = parseInt(e.loaded, 10) / parseInt(e.total, 10);percent = percent.toFixed(2) * 100;setTimeout(function () {var p = percent + "%";$(".progress span").css({ width: p });});});upload.send(function (err, data) {console.log(err);console.log(data);if (err) {alert("上传失败,请稍后重试");$("#progressInfo").css({ width: '0' });}//上传成功$.ajax({url: '/CompanyHandler.ashx',type: 'post',dataType: 'json',data: { action: 'saveVideo', object: data.Key, rand: Math.random() },success: function (result) {if (result.result == 1) {//关闭弹窗,刷新列表页parent.location.reload();}else {alert(result.description);}},error: function () {alert("发生异常,请稍后重试或联系客服反馈");}});filePicker.removeAttribute("disabled");});}</script>

S3 CORS


[{"AllowedHeaders": ["*"],"AllowedMethods": ["PUT","POST","DELETE"],"AllowedOrigins": ["https://*.cn"],"ExposeHeaders": ["ETag"]},{"AllowedHeaders": ["*"],"AllowedMethods": ["PUT","POST","DELETE"],"AllowedOrigins": ["http://*.jiaoyubao.cn"],"ExposeHeaders": ["ETag"]},{"AllowedHeaders": ["*"],"AllowedMethods": ["PUT","POST","DELETE"],"AllowedOrigins": ["http://localhost:53762"],"ExposeHeaders": ["ETag"]}
]

SQS异步通知机制

转码完成后会将完成消息写入SQS,业务侧可以通过读取SQS拿到消息,进行业务侧数据和逻辑完善。可以实现一个服务轮询SQS那消息,但由于SQS按照接口调用次数收费以及可以预测的大量的空队列读取情况,空队列读取依旧计入接口调用次数(aws有100万次的接口调用免费额度)。
基于以上考虑,使用SQSLambda 触发器实现推送机制,有消息到达SQS则触发Lambda函数,将消息推送给业务侧,需要自行编写Lambda函数。

VideoonDemand-Company-Notify

const http = require('http')exports.handler = async (event) => {const data = JSON.stringify(event);console.log(data)//其他业务复用当前部署堆栈的话,异步通知需要差异化的话,可以考虑通过视频前缀约束在此处进行差异化处理。const options = {hostname: 'vip3.shhddg.cn',port: 80,path: '/awsnotifications.aspx',method: 'POST',headers: {'Content-Type': 'application/json','Content-Length': data.length}}await new Promise(function (resolve, reject) {const req = http.request(options, res => {console.log(`状态码: ${res.statusCode}`)res.on('data', d => {})});req.on('error', error => {console.error(error)});req.write(data);req.end();                         });return event;
};

VideoonDemand-Company-Notify 要能够被SQS触发,需要配置对应的权限,创建的Lambda的执行角色需要加入AWSLambdaSQSExecutionRole 权限策略



域名解析到S3

将域名解析到S3 转码结果目标桶,并配置S3公开访问,从而可以使用域名访问S3资源。域名需要进行解析,注意需要去掉Host转发


CloudFormation部署的堆栈,默认会在当前账户创建CloudFront用于域名解析,仅做Dns解析调整即可。堆栈默认对S3桶权限做了配置。但目前的CloudFront统一在另外账户,不在当前部署堆栈的账户,因此,需要将域名直接解析到S3桶,并对S3桶设置了公开访问和策略调整,Principal设置了所有,默认是堆栈创建的对应域名的CloudFront用户允许。

🦉 Aws vs Aliyun

机构后台使用STS临时授权方案上传S3,对比阿里云接口调用和方式,Aws和阿里云从风格到接口基本一致。

阿里云

private AssumeRoleResponse GetStsToken()
{//获取sts凭证const string REGIONID = "cn-hangzhou";const string ENDPOINT = "sts.cn-yuenan.aliyuncs.com";// 构建一个 Aliyun Client, 用于发起请求// 构建Aliyun Client时需要设置AccessKeyId和AccessKeySevcretDefaultProfile.AddEndpoint(REGIONID, REGIONID, "Sts", ENDPOINT);IClientProfile profile = DefaultProfile.GetProfile(REGIONID, AppCode.ConstSetting.AccessKeyId, AppCode.ConstSetting.AccessKeySecret);DefaultAcsClient client = new DefaultAcsClient(profile);// 构造AssumeRole请求AssumeRoleRequest request = new AssumeRoleRequest();request.AcceptFormat = FormatType.JSON;// 指定角色Arnrequest.RoleArn = "acs:ram::14898694342448426:role/jiaoyubaovideorole";request.RoleSessionName = "upload";// 可以设置Token有效期,可选参数,默认3600秒;// request.DurationSeconds = 3600;// 可以设置Token的附加Policy,可以在获取Token时,通过额外设置一个Policy进一步减小Token的权限;// request.Policy="<policy-content>"try{AssumeRoleResponse response = client.GetAcsResponse(request);//Token过期时间;服务器返回UTC时间,这里转换成北京时间显示;return response;}catch (Exception ex){//Console.Write(ex.ToString());return null;}
}

Aws

private Amazon.SecurityToken.Model.AssumeRoleResponse GetOriginalAwsAssumeRole(int durationSeconds=3600)
{var roleArnToAssume = "arn:aws-cn:iam::7743242742862:role/ClientVideoUploadAssumeRole";var client = new Amazon.SecurityToken.AmazonSecurityTokenServiceClient(AWSCredentialsConfig.AwsAccessKeyId,AWSCredentialsConfig.AwsSecretAccessKey,Amazon.RegionEndpoint.CNNorthWest1);// Create the request to use with the AssumeRoleAsync call.var assumeRoleReq = new Amazon.SecurityToken.Model.AssumeRoleRequest(){DurationSeconds = durationSeconds,RoleSessionName = "AwsUpload",RoleArn = roleArnToAssume};var assumeRoleRes =  client.AssumeRole(assumeRoleReq);return assumeRoleRes;
}

🍄 避坑指南

坑1:文档版本不一致,不好找

服务商给到的视频点播文档中的方案链接https://www.amazonaws.cn/solutions/video-on-demand/?nc1=h_ls

搜索引擎或官方给到的视频点播文档链接https://aws.amazon.com/cn/solutions/implementations/video-on-demand-on-aws/

这两个链接的github源码不一致,而实现自定义定制功能的解决方案,在第一个链接中可以找到,第二个链接找不到。

坑2:SQS Lambda 触发器需要额外的权限

The provided execution role does not have permissions to call ReceiveMessage
Lambda函数 配置-权限-执行角色 的权限策略需要添加AWSLambdaSQSExecutionRole 策略

坑3:S3 CORS

分片上传ETag问题,使用分片上传的话ExposeHeaders务必设置ETag,否则会存在跨域问题,可参考以下文档
https://www.cnblogs.com/duhuo/p/14828021.html

[{"AllowedHeaders": ["*"],"AllowedMethods": ["PUT","POST","DELETE"],"AllowedOrigins": ["https://*.hfdhsa.cn"],"ExposeHeaders": ["ETag" //坑]},{"AllowedHeaders": ["*"],"AllowedMethods": ["PUT","POST","DELETE"],"AllowedOrigins": ["http://*.geertfd.cn"],"ExposeHeaders": ["ETag"]},{"AllowedHeaders": ["*"],"AllowedMethods": ["PUT","POST","DELETE"],"AllowedOrigins": ["http://localhost:53762" //坑,本地测试,多端口尚未解决],"ExposeHeaders": ["ETag"]}]

坑4:jssdk

var accessKeyId = "{$:token.Credentials.AccessKeyId}";
var accessKeySecret = "{$:token.Credentials.SecretAccessKey}";
var sessionToken = "{$:token.Credentials.SessionToken}";//坑,要传
//坑,要传,特别是协议cors
var endpoint = `${location.protocol}//s3.cn-northwest-1.amazonaws.com.cn`;
var s3 = new AWS.S3({ accessKeyId: accessKeyId, secretAccessKey: accessKeySecret, sessionToken: sessionToken, region: 'cn-northwest-1', endpoint: endpoint, signatureVersion: 'v4' });//坑 signatureVersion不指定报错

坑5:Lambda

需要重点了解和会编写脚本,比如Nodejs phython等解释性语言。如果使用Java或.NET需要编译的语言,需要按照官方文档实现开发,和打包成.gz文件上传到Aws,Aws提供了编译语言对应的运行环境,需要注意环境支持的版本等信息。建议使用解释性语言,好处是只要Aws提供了对应的解释器,就可以在线编写代码进行测试,缺点是无法本地调试或逐语句调试。即使使用解释性语言,复杂业务逻辑或引用第三方包,还是需要本地开发并打包成.gz文件上传到Aws。
Nodejs 支持异步的话,务必使用await,否则异步操作不会执行,比如:

 await new Promise(function (resolve, reject) {const req = http.request(options, res => {console.log(`状态码: ${res.statusCode}`)res.on('data', d => {})});req.on('error', error => {console.error(error)});req.write(data);req.end();                         });

相关文章:

阿里云迁移AWS视频点播技术攻坚

文章目录 &#x1f437; 背景&#x1f9a5; 简述&#x1f425; Aws服务&#x1f99c; AWS CloudFormation&#x1f41e; 问题&#x1f409; 落地方案&#x1f989; Aws vs Aliyun&#x1f344; 避坑指南 &#x1f437; 背景 由于AWS整体成本略低于阿里云&#xff0c;公司决定将…...

Scrum敏捷认证CSM官方认证班Certified ScrumMaster - CSM认证班

课程简介 Scrum是目前运用最为广泛的敏捷开发方法&#xff0c;是一个轻量级的项目管理和产品研发管理框架&#xff0c;旨在最短时间内交付最大价值。根据2021年全球敏捷状态报告&#xff0c;Scrum及Scrum衍生方法的应用占比达到81%。 在企业的敏捷转型历程中&#xff0c;Scru…...

深度解析qt核心机制:信号槽的多线程行为与对象的线程依附性

对象的线程依附性 每一个学过C以及系统编程的程序员&#xff0c;对于变量会与特定线程有关联都会感到不可思议&#xff1b;在qt中所说的对象的线程依附性&#xff0c;只是针对继承自QObject的对象而言的&#xff1b;对象的线程依附性&#xff0c;并不是代表真的某个底层线程才…...

关于时间格式yyyy-M-d或yyyy-MM-d到yyyy-MM-dd的转换

工作时遇到前端传的时间格式是"2023-12-3 17:41:52"&#xff0c;和"2023-1-1 17:41:52"但是我想要的是"2023-12-03 17:41:52"和"2023-01-01 17:41:52"。下面给大家分享几个解决方法 方法一&#xff1a; 找前端&#xff01;让他改&…...

【Windows】之微软输入法配置小鹤双拼

前言 Windows 自带的输入法微软输入法本身就是个最简洁、最方便的输入法&#xff0c;不需要去安装多余的第三方输入法软件。同时&#xff0c;微软中文拼音输入法支持双拼输入法&#xff0c;但微软自带的双拼输入法不包含小鹤双拼方案的。所以&#xff0c;在这里将会讲解如何配置…...

【AI】使用Jan.ai在本地部署大模型开启AI对话(含通过huggingface下载大模型,实现大模型自由)

文章目录 前言一、Jan.ai是什么&#xff1f;二、下载大模型1. 找到大模型文件地址2. 下载大模型3. 修改model.json文件 三、使用Jan调用大模型进行对话总结 前言 2023年是AIGC元年。以后&#xff0c;每个人多少都会接触到GPT带来的变化。别人都在用&#xff0c;我们也不能落下…...

C++摸版(初阶)----函数模版与类模版

本专栏内容为&#xff1a;C学习专栏&#xff0c;分为初阶和进阶两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握C。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&…...

Embedded-Project项目介绍

Embedded-Project项目介绍 Server后端项目后端启动连接数据库启动时可能遇到的问题架构介绍 web前端项目前端启动启动时可能遇到的问题架构介绍 前后端分离开发流程 项目地址&#xff1a; https://github.com/Catxiaobai/Embedded-Project Server后端项目 系统后端项目&#…...

golang 的那些花样

从 A Tour of Go 可以看到一些 Go 比较特殊的点 文章目录 变量声明时&#xff0c;类型放在后面Array 的引用 Slicereceiver 和 argumentbuilt-int特殊接口Error 变量声明时&#xff0c;类型放在后面 var i, j int 1, 2declaration-syntax Array 的引用 Slice slices-intro …...

如何设计企业级业务流程?学习华为的流程六级分类经验

业务流程管理&#xff08;BPM&#xff09;是一种系统化的方法&#xff0c;用于分析、设计、执行、监控和优化组织的业务流程&#xff0c;以实现预期的目标和价值。业务流程管理中&#xff0c;流程的分级方法有多种&#xff0c;常见的有以下几种&#xff1a; APQC的流程分级方法…...

视频智能分析支持摄像头异常位移检测,监测摄像机异常位移变化,保障监控状态

我们经常在生产场景中会遇到摄像头经过风吹日晒&#xff0c;或者异常的触碰&#xff0c;导致了角度或者位置的变化&#xff0c;这种情况下&#xff0c;如果不及时做出调整&#xff0c;会导致原本的监控条件被破坏&#xff0c;发生事件需要追溯的时候&#xff0c;查不到对应位置…...

C++ UTF-8与GBK字符的转换 —基于Linux 虚拟机 (iconv_open iconv)

1、UTF-8 和 GBK 的区别 GBK&#xff1a;通常简称 GB &#xff08;“国标”汉语拼音首字母&#xff09;&#xff0c;GBK 包含全部中文字符。 UTF-8 &#xff1a;是一种国际化的编码方式&#xff0c;包含了世界上大部分的语种文字&#xff08;简体中文字、繁体中文字、英文、…...

云原生十二问

一、什么是云原生&#xff1f; 云原生是在云计算环境中构建、部署和管理现代应用程序的软件方法。现代企业希望构建高度可扩展、灵活且具有弹性的应用程序&#xff0c;可以快速更新以满足客户需求。为此&#xff0c;他们使用现代工具和技术&#xff0c;这些工具和技术本质上支…...

K8Spod组件

一个pod能包含几个容器 一个pause容器(基础容器/父容器/根容器&#xff09; 一个或者多个应用容器(业务容器) 通常一个Pod最好只包含一个应用容器&#xff0c;一个应用容器最好也只运行一个业务进程。 同一个Pod里的容器都是运行在同一个node节点上的&#xff0c;并且共享 net、…...

clickhouse-client INSERT CSV/TSV时跳过错误行

clickhouse-client INSERT CSV/TSV时跳过错误行 在使用clickhouse-client向ck中导入csv文件时&#xff0c;当csv中有个别行数据格式错误时&#xff0c;整个文件就插入失败了&#xff0c;经常会导致丢数据。 经过一番搜索&#xff0c;发现ck提供了两个参数可以跳过错误行&#x…...

直流稳压电源电路

一、稳压电源的技术指标及对稳压电源的要求 稳压电源的技术指标可以分为两大类&#xff1a;一类是特性指标&#xff0c;如输出电压、输出电滤及电压调节范围;另一类是质量指标&#xff0c;反映一个稳压电源的优劣&#xff0c;包括稳定度、等效内阻&#xff08;输出电阻&#x…...

记录爬虫编写步骤

本文讲解 Python 爬虫实战案例&#xff1a;抓取百度贴吧&#xff08;https://tieba.baidu.com/&#xff09;页面&#xff0c;比如 Python爬虫吧、编程吧&#xff0c;只抓取贴吧的前 5 个页面即可。今天一个毕业学生问到一个问题&#xff1a;不清楚编写爬虫的步骤&#xff0c;不…...

SpringBoot配置Swagger2与Swagger3

swagger是什么&#xff1f; 在平时开发中&#xff0c;一个好的API文档可以减少大量的沟通成本&#xff0c;还可以帮助新加入项目的同事快速上手业务。大家都知道平时开发时&#xff0c;接口变化总是很多&#xff0c;有了变化就要去维护&#xff0c;也是一件比较头大的事情。尤…...

C/C++ 枚举

目录 枚举概述 枚举的使用 枚举的大小计算 枚举的优点 C语言中的自定义类型有&#xff1a;结构 位段 枚举 联合 枚举概述 枚举顾名思义就是一一列举&#xff0c;把可能的取值一一列举。 比如我们现实生活中&#xff1a;一周的星期一到星期日是有限的7天&#xff0c…...

P12 音视频复合流——TS流讲解

前言 从本章开始我们将要学习嵌入式音视频的学习了 &#xff0c;使用的瑞芯微的开发板 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《Linux C应用编程&#xff08;概念类&#xff09;_C…...

三维重建 3D Gaussian Splatting:实时的神经场渲染

目录 概念理解三维高斯喷洒 渲染实例 依赖项: 编译报错: 预训练模型 13G:...

Django Web框架

1、创建PyCharm项目 2、安装框架 pip install django4.2.0 3、查看安装的包列表 4、使用命令创建django项目 django-admin startproject web 5、目录结构 6、运行 cd web python manage.py runserver7、初始化后台登录的用户名密码 执行数据库迁移生成数据表 python man…...

ARCGIS PRO SDK GeometryEngine.Intersection的GeometryDimensionType 枚举

描述几何对象的维度。与 GeometryEngine.Intersection 一起使用。 ​ 成员描述EsriGeometry0Dimension零维&#xff08;点或多点&#xff09;。EsriGeometry1Dimension一维&#xff08;折线&#xff09;。EsriGeometry2Dimension二维&#xff08;多边形或包络&#xff09;。Es…...

Web网页开发-CSS层叠样式表1-笔记

1.CSS的引入方式 (1)内嵌式&#xff1a;把style双标签写在head标签里面&#xff0c;可以影响同种标签 (2)行内式&#xff1a;把style写在标签内部&#xff0c;只能影响当前标签 (3)外链式&#xff1a;创建css文件&#xff0c;使用link将html文件和css文件连接起来 (4)导入式&am…...

如何预防变种.halo勒索病毒感染您的计算机?

尊敬的读者&#xff1a; 在数字时代&#xff0c;威胁网络安全的.halo勒索病毒日益猖狂。本文将深入介绍.halo病毒的攻击方式&#xff0c;以及针对被加密文件的恢复方法和预防措施。在面对被勒索病毒攻击导致的数据文件加密问题时&#xff0c;技术支持显得尤为重要&#xff0c;…...

短网址的新玩法,短到只剩域名

短网址大家应该都不陌生了&#xff0c;一句话就可以解释清楚&#xff0c;把一串很长的网址缩短到只有几个字符依然可以正常访问&#xff0c;缩短之后会更加简洁美观。 那大家见过的短网址一般长啥样呢&#xff0c;比如t.cn/xxxxx、dwz.cn/xxxxx、c1ns.cn/xxxxx。这些短网址都有…...

FA2016AA (MHz范围晶体单元超小型低轮廓贴片) 汽车

随着科技的不断发展&#xff0c;智能汽车逐渐成为人们出行的首选。而其中&#xff0c;频率范围在19.2 MHz ~ 54 MHz的晶体单元超小型低轮廓贴片&#xff08;FA2016AA&#xff09;为汽车打造更智能、更舒适、更安全的出行体验。FA2016AA贴片的外形尺寸为2.0 1.6 0.5 mm&#x…...

【设计模式之美】面向对象分析方法论与实现(一):需求分析方法论

文章目录 一. 需求举例二. 对案例进行需求分析1. 第一轮基础分析2. 第二轮分析优化3. 第三轮分析优化4. 第四轮分析优化5. 最终确定需求 三. 小结 本文主要描述&#xff1a; 面向对象的需求分析方法论 一. 需求举例 假设&#xff0c;你正在参与开发一个微服务。微服务通过 HTT…...

MySQL视图索引执行计划相关十五道面试题分享

目录 一. 视图 1.1 含义 1.2 操作 创建视图 修改视图 删除视图 查看视图 二. 索引 2.1 什么是索引 2.2 为什么要使用索引 2.3 优点 2.4 缺点 2.5 何时不适用索引 2.6 索引何时失效 三. 执行计划 3.1 什么是执行计划 3.2 执行计划的作用 四. 面试题 表结构 …...

vue绑定背景颜色或背景图片 和 nuxtjs动态设置background-image:

v-bind绑定样式表&#xff1a; ---------------------------------------------------------------------------------------------------- HTML写法: <div class"myItem" style"text-align:center; background-image:url(); background-size:auto 100% ;ba…...

muse做的网站怎么样/站长统计性宝app

说明&#xff1a; &#xff08;1&#xff09;本篇博客内容&#xff1a;开发【友情链接列表查询&#xff0c;接口】&#xff1b; &#xff08;2&#xff09;本篇博客需要注意的点&#xff1a; ● 根据业务特点&#xff0c;我们这儿查询友情链接&#xff0c;直接查询的所有的链接…...

网络营销企业有哪些/seo的内容有哪些

udevmonitor 的原理也是捕捉 netlink 的 socket 消息&#xff0c;这个消息是内核发出的&#xff0c;打印出来的消息跟我上面的小程序一样&#xff0c;2.6内核支持udev&#xff0c;udev是在用户空间实现的程序&#xff0c;在终端输入 udevmonitor(有的版本或许是 udevadm -monit…...

长沙私人做网站/网络广告推广

Ext.data.GroupingStore继承自Ext.data.Store,为Store增加了分组功能.其它用法与Store一致,惟一需要注意的是使用GroupingStore时必须指定sortInfo信息增加了配置属性 groupField : String//用于分组的字段groupOnSort : Boolean//如果为真,将依排序字段重新分组,默认为假remot…...

高端网站模板/网络广告有哪些

文章目录一、介绍二、知识点1. Lua脚本1.1 介绍1.2 使用2. Splash API2.1 介绍2.2 使用1.render.html2.render.png3.execute一、介绍 1.提供JavaScript渲染服务 2.带有HTTP API的轻量级浏览器 3.对接了Python中的Twisted和QT库 Splash文档&#xff1a;传送门 二、知识点 1.…...

网站上的图分辨率做多少/百度推广关键词技巧定价

服务器又出故障了&#xff0c;这次比较彻底——系统文件丢失:(不得已重做了系统。趁着这个重做系统&#xff0c;决定将MySQL自5.0升级到5.5。先是安装MySQL&#xff0c;然后&#xff0c;配置my.ini&#xff0c;如果没特别需求的话&#xff0c;可以使用默认的就行&#xff0c;日…...

用自己照片做衣服 杯子的是哪个网站/佛山旺道seo优化

Linux知识盲区整理grep相关用法整理linux命令详解之pwd命令USERADD命令详解Linux下的chkconfig命令详解Linux ntsysv命令主机ping虚拟机请求超时&#xff0c;虚拟机ping主机正常ping通导致ssh连接问题centos 如何查看操作系统是哪个版本主机ping通虚拟机&#xff0c;而不能用xs…...