FFmpeg Muxer HLS
使用FFmpeg命令来研究它对HLS协议的支持程度是最好的方法:
ffmpeg -h muxer=hls
Muxer HLS
Muxer hls [Apple HTTP Live Streaming]:Common extensions: m3u8.Default video codec: h264.Default audio codec: aac.Default subtitle codec: webvtt.
这里面告诉我们,FFmpeg中的Muxer hls实际上是对于Apple HTTP Live Streaming的一种实现(HLS,全称HTTP Live Streaming,是Apple公司发布的协议),这里明确说明了HLS只是一种封装格式而与编码无关。
默认的文件扩展名为m3u8
,我们在浏览器中观看动漫、电影的时候,可以使用工具去查看它里面的链接。最终,你大概率会发现这样一种m3u8
文件的访问链接。
FFmpeg的hls muxer默认支持的视频、音频和字幕的编码格式分别是:h264
、aac
和webvtt
。这也就意味着如果我们想要对其他编码格式的音频或者视频进行HLS封装,那么就需要显式地去指定这些编码格式。需要注意的是,这些其他的编码格式需要是HLS协议支持的编码格式。
假设我们需要对一个MP4文件进行HLS切片,更准确地说是将MP$的封装格式转换成HLS的封装格式,只不过HLS这个封装格式是由多个音视频文件和一个M3U8(该文件在HLS协议中被称为Media Playlist,用作指导这些切片后的音视频如何播放)组成的。
例子
多的不说,我这里找一个MP4文件,使用FFmpeg将其转换成hls的封装格式,看看会出现什么样的结果。
这里我使用ffprobe查看该MP4文件的编码,来明确是否需要进行转码操作:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test_input.mp4':Metadata:major_brand : isomminor_version : 512compatible_brands: isomiso2avc1mp41encoder : Lavf60.16.100Duration: 00:00:14.82, start: 0.000000, bitrate: 2662 kb/sStream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1200 [SAR 1:1 DAR 8:5], 2489 kb/s, 60 fps, 60 tbr, 15360 tbn (default)Metadata:handler_name : VideoHandlervendor_id : [0][0][0][0]Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 159 kb/s (default)Metadata:handler_name : SoundHandlervendor_id : [0][0][0][0]
你可以看到,视频编码h264
和音频编码aac
都是默认的,这意味着我们不需要转码。
因此,我们可以使用以下命令来进行转封装:
mkdir output & ffmpeg -i test_input.mp4 -c copy -f hls output/index.m3u8
使用命令来查看output
目录中的内容:
> tree output
output
├── index.m3u8
├── index0.ts
├── index1.ts
├── index2.ts
└── index3.ts> cat output/index.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:4.166667,
index0.ts
#EXTINF:4.166667,
index1.ts
#EXTINF:4.166667,
index2.ts
#EXTINF:2.366667,
index3.ts
#EXT-X-ENDLIST
此刻,output
目录中的所有内容,组成了HLS协议的封装格式,虽然它们由多个文件组成。
但是,当需要切片的文件变大时,index.m3u8
的内容会和实际的切片数量对不上,原因就是:默认的hls_list_size
的值为5
。因此,index.m3u8文件中只会记录最新的5个切片。使用-hls_list_size
能够自己指定这个值。
选项
额外指定一些选项,让HLS的切片符合你的需求。
start_number
设置开始的序列号,默认从0开始。这里我们设置序列号为1进行切片,那么产生的结果为:
> mkdir output & ffmpeg -i test_input.mp4 -c copy -f hls -start_number 1 output/index.m3u8
> tree output
output
├── index.m3u8
├── index1.ts
├── index2.ts
├── index3.ts
└── index4.ts
注意,生成的切片文件名的序列号和m3u8文件中的序列号是对应的。
hls_time
指定切片的时间长度,单位为秒,默认值为2,类型是float
。
> cat output/index.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:4.166667,
index0.ts
#EXTINF:4.166667,
index1.ts
#EXTINF:4.166667,
index2.ts
#EXTINF:2.366667,
index3.ts
#EXT-X-ENDLIST
#EXTINF
就是切片的时间长度,这里切片的时间长度为4.166667
,这和默认值2
不相符。这是什么原因导致的呢?我猜测,这可能是因为HLS对于每个切片的关键帧具有某种要求,导致了最终的切片时间按照原本视频的关键帧分布来进行切片。
使用-force_key_frames "expr:gte(t,n_forced*2)"
来让视频GOP大小为2秒,以此让切片能够按照我们所设置的参数运行:
$ ffmpeg -i test_input.mp4 \
> -f hls \
> -force_key_frames "expr:gte(t,n_forced*2)" \
> -hls_time 2 \
> output/index.m3u8$ cat output/index.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:3
#EXTINF:2.000000,
index3.ts
#EXTINF:2.000000,
index4.ts
#EXTINF:2.000000,
index5.ts
#EXTINF:2.000000,
index6.ts
#EXTINF:0.866667,
index7.ts
#EXT-X-ENDLIST
这证明我们的猜测是正确的。注意,由于-force_key_frames
选项改变了原本的视频帧,因此不能够指定-c copy
(如果指定,则会导致我们无法对原本的视频编码做出任何改变,-force_key_frames
就会失效)。
你可以看到上面只记录了5个切片,3 4 5 6 7
,而我们的切片明明是从0开始的,并且0 1 2
确实存在于output目录中,但却没有被m3u8文件记录,这就关系到-hls_list_size
的使用了
hls_list_size
前面说了,由于m3u8
这个Media Playlist只会记录最新的几个切片,这可能会导致播放错误。该选项默认值是5,当切片多于5个时,你就要考虑将其设置地大一些,防止切片错误。
hls_base_url
你可以指定切片的基础路径,比如:http://xxx.com/
。这样浏览器可以通过读取m3u8
文件,然后通过网络来访问这些切片。
比如:
> ffmpeg -i test_input.mp4 -c copy -f hls \
> -hls_base_url "http://www.aderversa.com/" \
> output/index.m3u8> cat output/index.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:4.166667,
http://www.aderversa.com/index0.ts
#EXTINF:4.166667,
http://www.aderversa.com/index1.ts
#EXTINF:4.166667,
http://www.aderversa.com/index2.ts
#EXTINF:2.316667,
http://www.aderversa.com/index3.ts
#EXT-X-ENDLIST
该选项通常和服务器配合使用。你设置了一个URL,然后浏览器可以通过从服务器获取m3u8
文件和视频切片文件。
远程播放HLS视频
在前面,我们已经知道了,HLS封装格式会生成以下文件:
output
├── index.m3u8
├── index0.ts
├── index1.ts
├── index2.ts
└── index3.ts
播放器拿到m3u8文件,它应该能够按照HLS协议并参考m3u8上的内容自主获取视频切片并播放。
这里我使用Qt6.6的QMediaPlayer
来播放m3u8文件(这样方便理解,实际上M3U8不包含视频数据,它只含有该怎样播放的信息)。
如何播放呢?抓住一个关键点:只要QMediaPlayer
拿到了M3U8文件,它就能够依照该M3U8文件播放上面的资源,而我们是不需要了解它具体如何播放的,因为播放器的开发者为我们完成了这部分工作。我们唯一需要关注的就是:如何让QMediaPlayer
获取到这份M3U8文件。
这里我在网上随便找一个M3U8文件的链接(随便找个不是很正规的视频网站一般都能够找到,查看其HTML代码你就能够发现隐藏在其中的M3U8文件):
具体是什么URL我就不放出来了。
我们可以发现该播放器需要一个M3U8的URL才能够播放。
我们将url=
后面的链接命名为VideoURL
,方便后续说明。
这里我们在浏览器中请求VideoURL
,看看会发生什么?结果就是,浏览器给我们下载了一个M3U8文件。
我们使用以下Qt6.6中的代码来播放VideoURL
,看看能否播放成功:
int main(int argc, char *argv[])
{QApplication a(argc, argv);QMediaPlayer player;player.setSource(QUrl("https://play.modujx11.com/20250104/pZZhNChc/index.m3u8"));QVideoWidget video_widget;player.setVideoOutput(&video_widget);video_widget.show();QAudioOutput audio_output;player.setAudioOutput(&audio_output);player.play();return a.exec();
}
结果是,播放成功了。
这说明了什么呢?说明了只要服务器能够提供一个接口,让浏览器能够通过访问该接口URL下载到M3U8文件,且M3U8中的资源是可以被浏览器访问到的,那么实现了HLS协议的播放器应该就能播放该M3U8文件。
利用上面实验出来的特性搭建视频平台的一些猜想
那么,如果我们的应用程序想要通过HLS协议实现视频远程播放的功能,首先客户端需要有M3U8文件并进行播放的能力;而服务器只需要提供下载M3U8文件和下载M3U8文件中对应的切片文件的接口即可。
若应用程序能够播放的视频是服务器端规定好的,用户无法上传任何视频,那么我们在服务器端完全可以自己在相应的文件夹下使用FFmpeg命令来慢慢进行切片。
若用户可在应用程序中上传视频,那么上传完成之后,服务器端如果不追求性能和定制化,我个人认为直接调用FFmpeg的命令行程序来完成HLS的切片是没有问题的。如果用户上传的视频的编码或者封装格式不合适,那么要么禁止用户上传这类视频;要么就在后端慢慢进行转码,若同一时间有大量转码的视频,那么对于性能的消耗将是灾难性的,因此大部分应用程序都不会允许用户将格式不合适的视频直接上传到服务器端,而是让用户自行找方法转码,转码完成后再发送到服务器端。
用户若是能够上传视频,如果应用程序具有一定的用户基数,那么上传的视频数量大概率是会逐渐增加的,对服务器的性能要求也会逐渐提高(不管是空间上还是时间上)。
应用程序可能一开始就是将这些视频开放给所有用户的,用户可以通过客户端来访问或自己上传的、或别人上传的视频数据。我们可能需要使用数据库存业务数据 + 文件系统存视频数据 + 数据库和文件系统之间存在某种数据上的联系,以此数据存储为基础构建服务器,然后客户端/前端再基于服务器的接口构建符合需求的交互界面。
实现一个简单的服务器来验证猜想
首先,在SpringBoot中实现这样一个Controller,用来下载服务器上的文件:
@Controller
public class FileDownloadController {private static final String FILE_DIR = "/videos";@GetMapping("/download/{dirname}/{filename:.+}")@ResponseBodypublic ResponseEntity<Resource> downloadFile(@PathVariable("dirname") String dirname,@PathVariable("filename") String filename) {String path = System.getProperty("user.dir") + FILE_DIR + "/" + dirname;Path media_list_path = Paths.get(path).resolve(filename).normalize();try {UrlResource resource = new UrlResource(media_list_path.toUri());if (resource.exists() || resource.isReadable()) {return ResponseEntity.ok().contentType(MediaType.APPLICATION_OCTET_STREAM).header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"").body(resource);}else {return ResponseEntity.notFound().build();}}catch (Exception e) {e.printStackTrace();return ResponseEntity.status(500).build();}}
}
接着,我们在指定的/videos目录下创建好HLS封装的文件:
> ffmpeg -i hls_video.mp4 -f hls \
> -hls_base_url \
> http://127.0.0.1:8080/download/hlstest1/ \
> -c copy \
> -hls_list_size 1000 \
> hlstest1/index.m3u8> tree .
.
├── hls_video.mp4
└── hlstest1├── index.m3u8├── index0.ts├── index1.ts...
大致内容如上所示,然后在替换Qt原本代码中的URL成http://localhost:8080/download/hlstest1/index.m3u8,播放成功。
我这里的服务器运行在本机中,所以ip为localhost。
相关文章:
![](https://i-blog.csdnimg.cn/img_convert/a8607eac360b15d4fe8d3a2cb305551c.png)
FFmpeg Muxer HLS
使用FFmpeg命令来研究它对HLS协议的支持程度是最好的方法: ffmpeg -h muxerhls Muxer HLS Muxer hls [Apple HTTP Live Streaming]:Common extensions: m3u8.Default video codec: h264.Default audio codec: aac.Default subtitle codec: webvtt. 这里面告诉我…...
![](https://i-blog.csdnimg.cn/img_convert/ad90abf88be5a206bb543aef6d6d1ac7.png)
如何用SQL语句来查询表或索引的行存/列存存储方式|OceanBase 用户问题集锦
一、问题背景 自OceanBase 4.3.0版本起,支持了列存引擎,允许表和索引以行存、纯列存或行列冗余的形式创建,且这些存储方式可以自由组合。除了使用 show create table命令来查看表和索引的存储类型外,也有用户询问如何通过SQL语句…...
![](https://i-blog.csdnimg.cn/direct/d42aae37f0a84104bd3a732241fbec0b.png)
回归预测 | MATLAB实GRU多输入单输出回归预测
回归预测 | MATLAB实GRU多输入单输出回归预测 目录 回归预测 | MATLAB实GRU多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 回归预测 | MATLAB实GRU多输入单输出回归预测。使用GRU作为RNN的一种变体来处理时间序列数据。GRU相比传统的RNN有较好的记…...
![](https://i-blog.csdnimg.cn/direct/d8ffb62f4c044ccdbdccd8324c6a9d45.png#pic_center)
【OpenGL/Assimp】渲染模型、半透明材质与封装光源
文章目录 渲染成果Assimp库准备:Mesh类修改:透明贴图使用:光源封装:使用方式在如下测试环境中: 渲染成果 Assimp库准备: 从GitHub拉取源码,根据网络教程,借助CMake生成VS工程项目&a…...
![](https://www.ngui.cc/images/no-images.jpg)
pandas与sql对应关系【帮助sql使用者快速上手pandas】
本页旨在提供一些如何使用pandas执行各种SQL操作的示例,来帮助SQL使用者快速上手使用pandas。 目录 SQL语法一、选择SELECT1、选择2、添加计算列 二、连接JOIN ON1、内连接2、左外连接3、右外连接4、全外连接 三、过滤WHERE1、AND2、OR3、IS NULL4、IS NOT NULL5、B…...
![](https://www.ngui.cc/images/no-images.jpg)
Linux WEB漏洞
定义:Linux Web 漏洞是指在基于 Linux 操作系统的 Web 应用程序、Web 服务器软件或者相关的网络服务配置中存在的安全弱点。这些漏洞可能导致攻击者未经授权访问敏感信息、篡改网页内容、执行恶意代码,甚至完全控制服务器。 常见类型及原理 SQL 注入漏…...
![](https://i-blog.csdnimg.cn/direct/45f22ee579e8480d9e0aed501504ec45.png)
音视频入门基础:RTP专题(2)——使用FFmpeg命令生成RTP流
通过FFmpeg命令可以将一个媒体文件转推RTP: ffmpeg -re -stream_loop -1 -i input.mp4 -c:v copy -an -f rtp rtp://192.168.0.102:5400 但是通过ffplay尝试播放上述产生的RTP流时会报错:“Unable to receive RTP payload type 96 without an SDP file …...
![](https://i-blog.csdnimg.cn/direct/448c2d1066014260a814b6a1015a5f8f.png)
大语言模型预训练、微调、RLHF
转发,如有侵权,请联系删除: 1.【LLM】3:从零开始训练大语言模型(预训练、微调、RLHF) 2.老婆饼里没有老婆,RLHF里也没有真正的RL 3.【大模型微调】一文掌握7种大模型微调的方法 4.基于 Qwen2.…...
![](https://i-blog.csdnimg.cn/direct/7f2aa44b65374e2b8510407d61d267bb.png)
vue3后台系统动态路由实现
动态路由的流程:用户登录之后拿到用户信息和token,再去请求后端给的动态路由表,前端处理路由格式为vue路由格式。 1)拿到用户信息里面的角色之后再去请求路由表,返回的路由为tree格式 后端返回路由如下: …...
![](https://i-blog.csdnimg.cn/direct/8a0bbd49d20a414f8de97d0a77118c76.png)
解决idea中无法拖动tab标签页的问题
1、按 Ctrl Alt S 打开设置,找到路径 File | Settings | Appearance & Behavior | Appearance 2、去掉勾选 Drag-and-drop with Alt pressed only 即可...
![](https://i-blog.csdnimg.cn/direct/0fa664f61809449c93ff682d6b8b35d7.png)
WMS仓库管理系统,Vue前端开发,Java后端技术源码(源码学习)
一、项目背景和建设目标 随着企业业务的不断扩展,仓库管理成为影响生产效率、成本控制及客户满意度的重要环节。为了提升仓库作业的透明度、准确性和效率,本方案旨在构建一套全面、高效、易用的仓库管理系统(WMS)。该系统将涵盖库…...
![](https://i-blog.csdnimg.cn/direct/c0bd22ec97b4424790b1842aa91acee9.png)
25/1/12 嵌入式笔记 学习esp32
了解了一下位选线和段选线的知识: 位选线: 作用:用于选择数码管的某一位,例如4位数码管的第1位,第2位) 通过控制位选线的电平(高低电平),决定当前哪一位数码管处于激活状…...
![](https://i-blog.csdnimg.cn/direct/f0311454ea414663a7aa6e47cbdf061b.png)
【NLP】ELMO、GPT、BERT、BART模型解读及对比分析
文章目录 一、基础知识1.1 Word Embedding(词嵌入)1.2 词嵌入模型1.3 神经网络语言模型NNLM 二、ELMO2.1 ELMO的提出2.2 ELMO核心思想2.3 ELMO的优缺点 三、GPT3.1 Transformer3.2 GPT简介3.3 GPT模型架构3.4 预训练及微调3.5 GPT和ELMO对比 四、BERT4.1…...
![](https://www.ngui.cc/images/no-images.jpg)
go语言学习(数组,切片,字符串)
字符串 如果里面存储的是汉字,那么其实就是存储的是UTF--8编码,所以一个字会对应多个字节.如果想要获取汉字的个数,可以使用rune,来处理unicode字符 length: utf8.RuneCountInString( s) 如果只使用len()获取的是字节的个数, 字符串的功能 1,获取字节长度 len(xx) 2,获取字…...
![](https://i-blog.csdnimg.cn/direct/9159e15d8cd64a738a0b061b496a9b56.png#pic_center)
PM 实战 - 智能药盒PRD + 市场规模分析
写在前面 智能硬件 PRD 实例资源很少,Po下个人作品,假定前提为to Boss需求,目标在于覆盖产品设计核心部分(用户画像Persona、产品逻辑图、产品架构图、软件原型图、硬件低保真设计、用例Use Case、硬件标准)。不是申请…...
![](https://www.ngui.cc/images/no-images.jpg)
SQL刷题快速入门(二)
其他章节:SQL刷题快速入门(一) 承接上一章节,本章主要讲SQL的运算符、聚合函数、SQL保留小数的几种方式三个部分 运算符 SQL 支持多种运算符,用于执行各种操作,如算术运算、比较、赋值、逻辑运算等。以下…...
![](https://i-blog.csdnimg.cn/direct/0df0f4c1aac142a6a44907866ae83e79.png)
hive迁移后修复分区慢,怎么办?
我有1个30TB的分区表,客户给的带宽只有600MB,按照150%的耗时来算,大概要迁移17小时。 使用hive自带的修复分区命令(一般修复分区比迁移时间长一点),可能要花24小时。于是打算用前面黄大佬的牛B方案。 Hive增…...
![](https://i-blog.csdnimg.cn/direct/7aee8fa71e9b4d129d4b6ec75ea7cffd.png)
代码随想录算法训练营day27
代码随想录算法训练营 —day27 文章目录 代码随想录算法训练营前言一、贪心算法理论基础二、455.分发饼干三、376. 摆动序列53. 最大子数组和总结 前言 今天是算法营的第27天,希望自己能够坚持下来! 今日任务: ● 贪心算法理论基础 ● 455.…...
![](https://www.ngui.cc/images/no-images.jpg)
python 代码使用 DeepXDE 库实现了一个求解二维非线性偏微分方程(PDE)的功能
import deepxde as dde import numpy as np import matplotlib.pyplot as plt import tensorflow as tf# 设置时空计算域 Lx 1 # x 范围从 0 到 1 Ly 1 # y 范围从 0 到 1 Lt 0.05 # t 范围从 0 到 0.05 geom dde.geometry.Rectangle([0, 0], [Lx, Ly]) # 空间域 timed…...
![](https://www.ngui.cc/images/no-images.jpg)
【Go】:深入解析 Go 1.24:新特性、改进与最佳实践
前言 Go 1.24 尚未发布。这些是正在进行中的发布说明。Go 1.24 预计将于 2025 年 2 月发布。本文将深入探讨 Go 1.24 中引入的各项更新,并通过具体示例展示这些变化如何影响日常开发工作,确保为读者提供详尽而有价值的参考。 新特性及改进综述 HTTP/2 …...
![](https://www.ngui.cc/images/no-images.jpg)
VUE3 一些常用的 npm 和 cnpm 命令,涵盖了修改源、清理缓存、修改 SSL 协议设置等内容。
以下是一些常用的 npm 和 cnpm 命令,涵盖了修改源、清理缓存、修改 SSL 协议设置等内容。 npm 常用命令 1. 修改 npm 源 更改为淘宝的 npm 镜像源(可以提高安装速度): bash复制代码 npm config set registry https://registry…...
![](https://i-blog.csdnimg.cn/direct/1392a29463334c718404b05820f35467.png)
【SpringBoot】@Value 没有注入预期的值
问题复现 在装配对象成员属性时,我们常常会使用 Autowired 来装配。但是,有时候我们也使用 Value 进行装配。不过这两种注解使用风格不同,使用 Autowired 一般都不会设置属性值,而 Value 必须指定一个字符串值,因为其…...
![](https://i-blog.csdnimg.cn/img_convert/999914bb6f27183fcb8d724a184125c4.png)
【STM32-学习笔记-6-】DMA
文章目录 DMAⅠ、DMA框图Ⅱ、DMA基本结构Ⅲ、不同外设的DMA请求Ⅳ、DMA函数Ⅴ、DMA_InitTypeDef结构体参数①、DMA_PeripheralBaseAddr②、DMA_PeripheralDataSize③、DMA_PeripheralInc④、DMA_MemoryBaseAddr⑤、DMA_MemoryDataSize⑥、DMA_MemoryInc⑦、DMA_DIR⑧、DMA_Buff…...
![](https://www.ngui.cc/images/no-images.jpg)
js实现一个可以自动重链的websocket客户端
class WebSocketClient {constructor(url, callback, options {}) {this.url url; // WebSocket 服务器地址this.options options; // 配置选项(例如重试间隔、最大重试次数等)this.retryInterval options.retryInterval || 1000; // 重试间隔&#…...
![](https://i-blog.csdnimg.cn/direct/1f83243264654573ad5ea433298f0fb7.png)
企业总部和分支通过GRE VPN互通
PC1可以ping通PC2 1、首先按照地址表配置ip地址 2、分别在AR1和AR3上配置nat 3、配置GRE a 创建tunnel接口,并选择tunnel协议为GRE,为隧道创建一个地址,用作互联 b 为隧道配置源地址或者源接口,这里选择源接口;再为…...
![](https://i-blog.csdnimg.cn/direct/195b775d9e0a4e11a909e8f9063c738d.png)
油猴支持阿里云自动登陆插件
遇到的以下问题,都已在脚本中解决: 获取到的元素赋值在页面显示,但是底层的value并没有改写,导致请求就是获取不到数据元素的加载时机不定,尤其是弱网情况下,只靠延迟还是有可能获取不到,且登陆…...
![](https://i-blog.csdnimg.cn/direct/918242775f684d628b7dcf2ee74eb48c.png)
【2024年华为OD机试】(C卷,100分)- 字符串筛选排序 (Java JS PythonC/C++)
一、问题描述 题目描述 输入一个由N个大小写字母组成的字符串 按照ASCII码值从小到大进行排序 查找字符串中第K个最小ASCII码值的字母 (k > 1) 输出该字母所在字符串中的位置索引 (字符串的第一个位置索引为0) k如果大于字符串长度则输出最大ASCII码值的字母所在字符串…...
![](https://www.ngui.cc/images/no-images.jpg)
iOS - runtime总结
详细总结一下 Runtime 的核心内容: 1. 消息发送机制 // 消息发送的基本流程 id objc_msgSend(id self, SEL _cmd, ...) {// 1. 获取 isaClass cls object_getClass(self);// 2. 查找缓存IMP imp cache_getImp(cls, _cmd);if (imp) return imp(self, _cmd, ...);…...
![](https://i-blog.csdnimg.cn/img_convert/0ede82cc25798a0aebfb5d2927a2a678.png)
第33 章 - ES 实战篇 - MySQL 与 Elasticsearch 的一致性问题
思维导图 0. 前言 MySQL 与 Elasticsearch 一致性问题是老生常谈了。网上有太多关于这方面的文章了,但是千篇一律,看了跟没看没有太大区别。 在生产中,我们往往会通过 DTS 工具将 binlog 导入到 Kafka,再通过 Kafka 消费 binlog&…...
![](https://i-blog.csdnimg.cn/direct/59cffa2b60cf45b2a5f38743f4635abf.png#pic_center)
Artec Leo 3D扫描仪与Ray助力野生水生动物法医鉴定【沪敖3D】
挑战:捕获大型水生哺乳动物(如鲸鱼)的数据,搭建全彩3D模型,用于水生野生动物的法医鉴定、研究和保护工作。 解决方案:Artec Eva、Artec Space Spider、Artec Leo、Artec Ray、Artec Studio、CT scans 效果&…...
![](/images/no-images.jpg)
内网网站建设软件/微信营销平台
WITH提供了一种方式来书写在一个大型查询中使用的辅助语句。这些语句通常被称为公共表表达式或CTE,他们可以被看成是定义只在一个查询中存在的临时表。在WITH子句中的每一个辅助语句可以是一个SELECT、INSERT、UPDATE或DELETE,并且WITH子句本身也可以被附…...
![](https://img-blog.csdnimg.cn/20201107155120784.png#pic_center)
wordpress sqllite/网络营销的概述
一、建立一个测试计划(test plan) 之前有说过,jmeter打开后会自动生成一个空的test plan,用户可以基于该test plan建立自己的test plan 一个性能测试的负载必须有一个线程组完成,而一个测试计划必须有至少一个线程组…...
![](https://img-blog.csdnimg.cn/225f3fa7934c4946b666584fb3a11bc7.png)
宝塔面板加wordpress/长沙网站搭建优化
文章目录分布式仲裁流程?交换机路由方法?路由:网络延迟计算?线程级并行介绍?线程的不同粒度?并发和并行的区别?数据级并行有哪些?单指令流多线程流 SIMT ?分布式仲裁流程…...
![](https://img-blog.csdnimg.cn/f8567aa65d4d4a5295f6cb4c5c23a36a.png)
兰州论坛网站建设/问卷调查网站
with open(data.csv,modew,newline,encodingutf-8) as f:pass 今天在写入csv的时候发现文件多了一行空行,加上newline 就可以了 原:...
![](https://img-blog.csdnimg.cn/img_convert/ef52c2c18da3d656f7b1e1716f22455b.png)
做网站虚拟主机哪家好/百度广告一天多少钱
我们在使用 vue element 写后台管理模板时,肯定逃不过左侧菜单也称侧边栏。举例:我们现在有一个 A 模块,A 模块中有详情页面和编辑页面【一共三个页面】,我们通常怎么考虑?将三个页面写在一个 vue 里,通过…...
![](https://s1.51cto.com/attachment/201302/22/400469_1361492865bR6g.jpg)
北京宣传片制作公司/西安seo网站排名
使用组策略进行软件升级 升级包括强制升级和可选升级,强制升级就是强制用户卸载已经安装的旧版本软件,安装新版软件。可选升级就是保留旧版本的情况下安装新版本。 本示例演示强制升级部署给用户的画图软件。 任务: u 配置组策略使用版本2升级…...