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

MLT媒体程序框架03:滤镜——loudness

EBU R.128协议

引用链接
EBU的全称为European Broadcasting Union ,既欧洲广播联盟,为欧洲与北非各广播业者(包含广播电台与电视台)的合作组织,成立于1950年2月12日,有五十多个正式加盟国,总部位于瑞士日内瓦,目前中国是EBU的准会员。
EBU R.128实质上是欧洲广播联盟出的一个关于响度控制的建议书,该建议书在ITU-R BS.1770标准的(国际广播联盟规定的音频节目响度及真峰值的测量算法)基础之上,对响度的被测主体、积分窗长等细节作了更加明确的定义。

响度和动态范围的定义与相关的计量单位

  • 响度(Loudness)的定义: 在声学中,响度是人对声音压力的主观感受,也是听觉的一种属性,根据这种属性,可以对声音进行排序,如从安静排列到响亮,亦或者从响亮排列至安静。响度虽是声音的物理属性,但其却与听者的生理感受,心理感受息息相关,准确来说这属于心理物理学的范畴了。

  • 音量单位dBFS与dB: 首先dBFS与dB都是分贝的意思,而分贝一般指的就是音量大小。 dBFS全称decibels relative to full scale,什么叫full scale呢?既是满刻度,具体来讲是将0作为这种满刻度单位的最大值(也就是说此类值均为负数),凡是带FS后缀的计量单位都可这样理解(如LUFS或LKFS)。dB常用来形容一个音量到目标音量的“距离”,比如需要将一个信号从-4dBFS提升至-1dBFS,那么就需要对-4dBFS做3dB的提升操作。在业界,dBFS常被简称为dB,如-4dB等等。

  • 动态范围: 用通俗不严谨的话来说,动态范围指的是最大音量与最小音量之间的“距离”值,这个“距离”值就被称为动态范围,比如一段音频中的最大音量为-2dBFS,最小音量为-8dBFS,那么它的动态范围就是6dB。站在AD转换器的角度来说,动态范围指的是信号可以达到的最大不失真电平与本底噪声的差值。

  • EBU响度单位LUFS: LUFS的全称为Loudness units relative to full scale,既相对完整刻度的响度单位。广电行业中,LUFS是有一个目标响度值的,那就是-23LUFS,该值是广播世界的终极响度参考值!LUFS的数值越大,其响度就越大。至于为什么是-23LUFS,笔者暂未做深入研究。另外,LKFS是国际广播联盟用的单位,与LUFS差不多。

  • EBU响度单位LU: LU的全称为Loudness units,通常1LU“等同于”1dB(仅仅是理解层面上的“相等”),常用来形容两个LUFS之间的“距离”,如-25LUFS与-18LUFS间差了7LU。综上所述,dBFS与LUFS, dB与LU,虽测量算法不同,但其含义却是相似的。

响度示值,响度范围和真峰值的介绍

  • 瞬时响度 Momentary Loudness: 瞬时响度指的是400MS(毫秒)内的响度,并每过100ms进行一次更新,响应相当灵敏。
  • 短期响度 Short Term Loudness: 短期响度是提取3秒以内的信号,表达的是3S内的平均响度。
  • 综合响度 Integrated Loudness: 综合响度指的是整段音频的平均响度。
  • 响度范围 Loudness Range: 响度范围,经常被简称为LRA,其代表的是两个LUFS之间的“距离”,如一段音频的最小响度为-25LUFS,最大响度为-18LUFS,其间差了7LU,既代表该音频的响度范围为7LU。响度范围与动态范围表达的是一个意思,只是测量方法不一样。
  • 真峰值 True Peak: 在说真峰值之前,先用通俗的话来说说峰值是什么,峰值就是波形振幅的波峰值(波形有波谷和波峰之分),说白了就是波形瞬态的最大电平值。那为什么要在峰值之前加个“真”字呢?原因是这样的,以前有一种峰值测量方法,只有当峰值的持续时间超过一定的时间时(通常是几毫秒),才会计算出比较准确的峰值,这种测量算法被称为准峰值(QPPM)。而EBU给出了一种新的算法,无论它的持续时间有多短,都能正确的测量出其波形的真实峰值水平,故此,称其为真峰值。那么响度表中的真峰值指示条是用来干嘛的呢?它是用来检测信号有没有过载的,一旦信号过载就会被削波造成信号失真,正因如此,EBU给出建议为真峰值不要超过-1dBTP,目的就是防止信号产生过载削波,其单位为dBTP(dB True Peak真实峰值),对应的值是dBFS值。

双遍滤镜(loudness)

主要用于音频向度的精准标准化,其核心作用是通过两次处理(Double Pass)分析音频特征并应用目标响度参数,确保输出音频符合行业标准(如EBU R128 或 ITU-R BS.1770),同时优化动态范围控制

使用方式

One Pass: 调用滤镜分析得到result

std::string AudioAnalyze::analyzeAudio(const std::string &path,int trimIn,int trimOut) {Producer producer(getGlobalProfile(), nullptr,path.c_str());if(producer.get_length() <= 1 || producer.get_int("audio_index") == -1){std::cout << "analyzeAudio no effect"  << std::endl;return "";}if(trimOut > 0){producer.set_in_and_out(trimIn,trimOut);}Filter filter(getGlobalProfile(),"loudness");filter.set("program",-29);producer.attach(filter);Consumer consumer(getGlobalProfile(), "null");consumer.set("terminate_on_pause",0);consumer.connect(producer);consumer.start();while (!consumer.is_stopped()) {// ignoreif(filter.property_exists("results")){const char *results = filter.get("results");if(results != nullptr) {std::cout << "analyzeAudio results:" << results << std::endl;consumer.stop();return results;} else {std::cout << "analyzeAudio results:" << "error: key is null" << std::endl;return "";}}}return "";
}

Two Pass: 把result写入滤镜参数中,则会自动调整目标响度

std::shared_ptr<Filter> loudnessFilter{nullptr};
if (!results.empty()) {loudnessFilter = std::make_shared<Filter>(getGlobalProfile(), "loudness");loudnessFilter->set("program", configuration.aiDefaultLoudness);loudnessFilter->set("disable", 0);loudnessFilter->set("reload", 1);auto length = results.length() + 1;char *result = (char *) malloc(results.length() + 1);memcpy((void *) result, (const void *) results.c_str(), results.length());result[length - 1] = '\0';loudnessFilter->set("results", result);
}
loudnessFilter->set_in_and_out(trimIn, trimOut);
childClipInfo->producer->attach(*loudnessFilter);

关键源码分析

filter_get_audio

static int filter_get_audio(mlt_frame frame,void **buffer,mlt_audio_format *format,int *frequency,int *channels,int *samples)
{mlt_filter filter = mlt_frame_pop_audio(frame);mlt_properties properties = MLT_FILTER_PROPERTIES(filter);mlt_service_lock(MLT_FILTER_SERVICE(filter));// Get the producer's audio*format = mlt_audio_f32le;mlt_frame_get_audio(frame, buffer, format, frequency, channels, samples);char *results = mlt_properties_get(properties, "results");if (buffer && buffer[0] && results && strcmp(results, "")) {// Two Pass的时候走这个函数apply(filter, frame, buffer, format, frequency, channels, samples);} else {// One Pass的时候走这个函数analyze(filter, frame, buffer, format, frequency, channels, samples);}mlt_service_unlock(MLT_FILTER_SERVICE(filter));return 0;
}

analyze:分析得到原音频信息

static void analyze(mlt_filter filter,mlt_frame frame,void **buffer,mlt_audio_format *format,int *frequency,int *channels,int *samples)
{private_data *private = (private_data *) filter->child;mlt_position pos = mlt_filter_get_position(filter, frame);// If any frames are skipped, analysis data will be incomplete.// 作用:确保音频帧按顺序处理,跳过帧会导致分析中断。// 原因:EBU R128 要求连续分析,缺失帧会导致积分响度计算错误。if (private->analyze && pos != private->last_position + 1) {mlt_log_error(MLT_FILTER_SERVICE(filter), "Analysis Failed: Bad frame sequence\n");destroy_analyze_data(filter);}// Analyze Audioif (!private->analyze && pos == 0) {init_analyze_data(filter, *channels, *frequency);}if (private->analyze) {// 作用:将当前音频帧数据(buffer)输入 EBU R128 分析器,更新内部状态。ebur128_add_frames_float(private->analyze->state, *buffer, *samples);if (pos + 1 == mlt_filter_get_length2(filter, frame)) {mlt_properties properties = MLT_FILTER_PROPERTIES(filter);double loudness = 0.0;double range = 0.0;double tmpPeak = 0.0;double peak = 0.0;int i = 0;char result[MAX_RESULT_SIZE];// 计算整体响度ebur128_loudness_global(private->analyze->state, &loudness);// 计算响度范围ebur128_loudness_range(private->analyze->state, &range);// 获取声道峰值for (i = 0; i < *channels; i++) {ebur128_sample_peak(private->analyze->state, i, &tmpPeak);if (tmpPeak > peak) {peak = tmpPeak;}}// 格式化结果并存储snprintf(result, MAX_RESULT_SIZE, "L: %lf\tR: %lf\tP %lf", loudness, range, peak);result[MAX_RESULT_SIZE - 1] = '\0';mlt_log_info(MLT_FILTER_SERVICE(filter), "Stored results: %s\n", result);mlt_properties_set(properties, "results", result);destroy_analyze_data(filter);}private->last_position = pos;}
}
ebur128_gated_loudness: 计算 综合响度(Integrated Loudness)

这段代码是 EBU R128 综合响度(Integrated Loudness) 的核心计算逻辑,用于在音频处理中通过门限控制(Gating)剔除低能量部分,最终得到符合标准的响度值。

static int
ebur128_gated_loudness(ebur128_state** sts, size_t size, double* out) {struct ebur128_dq_entry* it;double gated_loudness = 0.0;double relative_threshold = 0.0;size_t above_thresh_counter = 0;size_t i, j, start_index;// 检查输入的音频状态结构体数组 sts 是否启用了综合响度模式(EBUR128_MODE_I)。若未启用,返回错误。
// 综合响度模式是 EBU R128 的核心功能,需通过 ebur128_init 初始化时设置模式标志for (i = 0; i < size; i++) {if (sts[i] && (sts[i]->mode & EBUR128_MODE_I) != EBUR128_MODE_I) {return EBUR128_ERROR_INVALID_MODE;}}
// 作用:遍历所有音频状态实例,调用 ebur128_calc_relative_threshold 计算 相对门限
// 相对门限:基于音频块能量分布,动态确定一个阈值,剔除低于该值的部分(如静音段或背景噪声)
// 公式:相对门限 = 平均能量 × 相对门限因子(默认-10 dB,即 relative_gate_factor = 0.1)
// 引用:EBU R128 要求综合响度计算需忽略低于动态门限的音频段,以聚焦主要节目内容for (i = 0; i < size; i++) {if (!sts[i]) {continue;}ebur128_calc_relative_threshold(sts[i], &above_thresh_counter,&relative_threshold);}if (!above_thresh_counter) {*out = -HUGE_VAL;return EBUR128_SUCCESS;}relative_threshold /= (double) above_thresh_counter;relative_threshold *= relative_gate_factor;
// 作用:根据相对门限值,确定直方图中高于门限的起始索引 start_index。
// 直方图优化:若启用直方图模式(use_histogram),直接遍历预计算的能量区间,跳过低能量部分。
// 未启用直方图:则需遍历块链表(block_list),逐个检查能量是否高于门限。
// 引用:直方图加速了能量统计,是 EBU R128 实现高效计算的关键优化 above_thresh_counter = 0;if (relative_threshold < histogram_energy_boundaries[0]) {start_index = 0;} else {start_index = find_histogram_index(relative_threshold);if (relative_threshold > histogram_energies[start_index]) {++start_index;}}
// 作用:统计所有高于门限的音频块能量总和 gated_loudness 及其数量 above_thresh_counter。
// 直方图模式:通过预计算的能量值 histogram_energies 和直方图计数快速累加。
// 块链表模式:遍历链表,筛选符合门限的块并累加能量。
// 引用:EBU R128 要求忽略低于门限的音频段,例如静音或低电平背景声for (i = 0; i < size; i++) {if (!sts[i]) {continue;}if (sts[i]->d->use_histogram) {for (j = start_index; j < 1000; ++j) {gated_loudness +=sts[i]->d->block_energy_histogram[j] * histogram_energies[j];above_thresh_counter += sts[i]->d->block_energy_histogram[j];}} else {STAILQ_FOREACH(it, &sts[i]->d->block_list, entries) {if (it->z >= relative_threshold) {++above_thresh_counter;gated_loudness += it->z;}}}}if (!above_thresh_counter) {*out = -HUGE_VAL;return EBUR128_SUCCESS;}
// 作用:
//  平均能量:将累积的能量总和除以有效块数量,得到平均能量。
// 能量转响度:调用 ebur128_energy_to_loudness 将能量转换为 LUFS(Loudness Units Full Scale)。
// 公式:LUFS = 10 × log₁₀(平均能量) - 绝对偏移值(如-0.691 dB,用于校准滤波器响应)
// 引用:LUFS 是 EBU R128 的标准化响度单位,综合响度目标值为 -23 LUFS(广播领域)gated_loudness /= (double) above_thresh_counter;*out = ebur128_energy_to_loudness(gated_loudness);return EBUR128_SUCCESS;
}
ebur128_loudness_range_multiple:计算响度范围(Loudness Range, LRA)

用于衡量音频节目中响度的动态变化
计算多个音频流的综合响度范围(LRA),即节目中最响的 95% 部分与最安静的 10% 部分之间的响度差(单位:LU)

输入:
sts:多个 ebur128_state 状态对象的数组(支持多路音频流合并计算)。
size:数组长度。
输出:
out:计算得到的 LRA 值。
返回值:错误码(成功为 EBUR128_SUCCESS)。

int ebur128_loudness_range_multiple(ebur128_state** sts,size_t size,double* out) {size_t i, j;struct ebur128_dq_entry* it;double* stl_vector;size_t stl_size;double* stl_relgated;size_t stl_relgated_size;double stl_power, stl_integrated;/* High and low percentile energy */double h_en, l_en;int use_histogram = 0;// 模式校验
// 必须启用 LRA 模式:所有状态对象需通过 EBUR128_MODE_LRA 初始化。
// 直方图模式一致性:所有状态对象需统一启用或禁用直方图(EBUR128_MODE_HISTOGRAM)。for (i = 0; i < size; ++i) {if (sts[i]) {if ((sts[i]->mode & EBUR128_MODE_LRA) != EBUR128_MODE_LRA) {return EBUR128_ERROR_INVALID_MODE;}if (i == 0 && sts[i]->mode & EBUR128_MODE_HISTOGRAM) {use_histogram = 1;} else if (use_histogram != !!(sts[i]->mode & EBUR128_MODE_HISTOGRAM)) {return EBUR128_ERROR_INVALID_MODE;}}}
// 直方图模式计算if (use_histogram) {unsigned long hist[1000] = { 0 };size_t percentile_low, percentile_high;size_t index;stl_size = 0;stl_power = 0.0;for (i = 0; i < size; ++i) {if (!sts[i]) {continue;}for (j = 0; j < 1000; ++j) {// 直方图累加:合并所有音频流的短期能量直方图(3秒窗口)。hist[j] += sts[i]->d->short_term_block_energy_histogram[j];stl_size += sts[i]->d->short_term_block_energy_histogram[j];stl_power += sts[i]->d->short_term_block_energy_histogram[j] *histogram_energies[j];}}if (!stl_size) {*out = 0.0;return EBUR128_SUCCESS;}
//门限处理:排除低于平均能量 -20 dB 的块(minus_twenty_decibels = 0.01)。// 平均能量stl_power /= stl_size;// // 应用-20 dB门限stl_integrated = minus_twenty_decibels * stl_power;if (stl_integrated < histogram_energy_boundaries[0]) {index = 0;} else {// 找到门限对应的直方图索引(直方图优化:跳过低于门限的区间,减少计算量。)index = find_histogram_index(stl_integrated);if (stl_integrated > histogram_energies[index]) {++index;}}stl_size = 0;for (j = index; j < 1000; ++j) {stl_size += hist[j];}if (!stl_size) {*out = 0.0;return EBUR128_SUCCESS;}
// 遍历直方图:累加直方图计数,找到对应百分位的能量值。// 10% 低百分位percentile_low = (size_t) ((stl_size - 1) * 0.1 + 0.5);// 95% 高百分位percentile_high = (size_t) ((stl_size - 1) * 0.95 + 0.5);stl_size = 0;j = index;while (stl_size <= percentile_low) {stl_size += hist[j++];}l_en = histogram_energies[j - 1];while (stl_size <= percentile_high) {stl_size += hist[j++];}h_en = histogram_energies[j - 1];
// 计算 LRA(将能量值转换为响度(LU),计算高低百分位的差值*out = ebur128_energy_to_loudness(h_en) - ebur128_energy_to_loudness(l_en);return EBUR128_SUCCESS;}
// 非直方图模式计算同理stl_size = 0;for (i = 0; i < size; ++i) {if (!sts[i]) {continue;}STAILQ_FOREACH(it, &sts[i]->d->short_term_block_list, entries) {++stl_size;}}if (!stl_size) {*out = 0.0;return EBUR128_SUCCESS;}stl_vector = (double*) malloc(stl_size * sizeof(double));if (!stl_vector) {return EBUR128_ERROR_NOMEM;}j = 0;for (i = 0; i < size; ++i) {if (!sts[i]) {continue;}STAILQ_FOREACH(it, &sts[i]->d->short_term_block_list, entries) {stl_vector[j] = it->z;++j;}}qsort(stl_vector, stl_size, sizeof(double), ebur128_double_cmp);stl_power = 0.0;for (i = 0; i < stl_size; ++i) {stl_power += stl_vector[i];}stl_power /= (double) stl_size;stl_integrated = minus_twenty_decibels * stl_power;stl_relgated = stl_vector;stl_relgated_size = stl_size;while (stl_relgated_size > 0 && *stl_relgated < stl_integrated) {++stl_relgated;--stl_relgated_size;}if (stl_relgated_size) {h_en = stl_relgated[(size_t) ((stl_relgated_size - 1) * 0.95 + 0.5)];l_en = stl_relgated[(size_t) ((stl_relgated_size - 1) * 0.1 + 0.5)];free(stl_vector);*out = ebur128_energy_to_loudness(h_en) - ebur128_energy_to_loudness(l_en);} else {free(stl_vector);*out = 0.0;}return EBUR128_SUCCESS;
}
ebur128_sample_peak:获取指定声道采样峰值(Sample Peak)

作用:获取音频流中指定声道的采样峰值电平(单位:dBFS)。
采样峰值(Sample Peak):音频信号在数字域中的最大绝对值,未经插值处理,直接来自采样点。
用途:检测音频是否削波(超过 0 dBFS),确保符合广播或流媒体的响度标准。

int ebur128_sample_peak(ebur128_state* st,unsigned int channel_number,double* out) {if ((st->mode & EBUR128_MODE_SAMPLE_PEAK) != EBUR128_MODE_SAMPLE_PEAK) {return EBUR128_ERROR_INVALID_MODE;}if (channel_number >= st->channels) {return EBUR128_ERROR_INVALID_CHANNEL_INDEX;}*out = st->d->sample_peak[channel_number];return EBUR128_SUCCESS;
}

apply

核心目标:将音频的响度调整到用户设定的目标值(如 EBU R128 规定的 -23 LUFS)。
输入依赖:需要预先通过分析阶段获取当前音频的响度(in_loudness)、响度范围(in_range)和峰值(in_peak)。
操作:计算增益系数并应用到音频数据,使其响度匹配目标值。

static void apply(mlt_filter filter,mlt_frame frame,void **buffer,mlt_audio_format *format,int *frequency,int *channels,int *samples)
{mlt_properties properties = MLT_FILTER_PROPERTIES(filter);char *results = mlt_properties_get(properties, "results");double in_loudness;double in_range;double in_peak;int scan_return = sscanf(results, "L: %lf\tR: %lf\tP %lf", &in_loudness, &in_range, &in_peak);if (scan_return != 3) {mlt_log_error(MLT_FILTER_SERVICE(filter), "Unable to load results: %s\n", results);} else {// 计算增益系数// 增益公式是固定的double target_db = mlt_properties_get_double(properties, "program");double delta_db = target_db - in_loudness;double coeff = delta_db > -90.0 ? pow(10.0, delta_db / 20.0) : 0.0;float *p = *buffer;int count = *samples * *channels;// 线性增益:将每个音频样本乘以计算出的增益系数。// 声道处理:遍历所有声道和样本,统一应用增益。for (int i = 0; i < count; i++) {p[i] = p[i] * coeff;}}
}

相关文章:

MLT媒体程序框架03:滤镜——loudness

EBU R.128协议 引用链接 EBU的全称为European Broadcasting Union &#xff0c;既欧洲广播联盟&#xff0c;为欧洲与北非各广播业者&#xff08;包含广播电台与电视台&#xff09;的合作组织&#xff0c;成立于1950年2月12日,有五十多个正式加盟国,总部位于瑞士日内瓦,目前中国…...

FreeRTOS第15篇:FreeRTOS链表实现细节03_List_t与ListItem_t的奥秘

文/指尖动听知识库-星愿 文章为付费内容,商业行为,禁止私自转载及抄袭,违者必究!!! 文章专栏:深入FreeRTOS内核:从原理到实战的嵌入式开发指南 1 FreeRTOS列表的核心数据结构 FreeRTOS的列表实现由两个关键结构体组成:List_t(列表)和ListItem_t(列表项)。它们共同…...

Spring Boot静态资源访问顺序

在 Spring Boot 中&#xff0c;static 和 public 目录都用于存放静态资源&#xff08;如 HTML、CSS、JavaScript、图片等文件&#xff09;&#xff0c;但它们在使用上有一些细微的区别。以下是它们的详细对比&#xff1a; 1. 默认优先级 Spring Boot 会按照以下优先级加载静态…...

什么是 spring 的循环依赖?

什么是 spring 的循环依赖&#xff1f; 首先&#xff0c;认识一下什么是循环依赖&#xff0c;举个例子&#xff1a;A 对象被 Spring 管理&#xff0c;并且引入的 B 对象&#xff0c;同样的 B 对象也被 Spring 管理&#xff0c;并且也引入的 A 对象。这种相互被引用的情况&#…...

RSA的理解运用与Pycharm组装Cryptodome库

1、RSA的来源 RSA通常指基于RSA算法的密码系统&#xff0c;令我没想到的是&#xff0c;其名字的来源竟然不是某个含有特别意义的单词缩写而成&#xff08;比如PHP&#xff1a;Hypertext Preprocessor(超文本预处理器)&#xff09;&#xff0c;而是由1977年提出该算法的三个歪果…...

AI数据分析:deepseek生成SQL

在当今数据驱动的时代&#xff0c;数据分析已成为企业和个人决策的重要工具。随着人工智能技术的快速发展&#xff0c;AI 驱动的数据分析工具正在改变我们处理和分析数据的方式。本文将着重介绍如何使用 DeepSeek 进行自动补全SQL 查询语句。 我们都知道&#xff0c;SQL 查询语…...

git的坑

不小心把工作区的代码全删掉了 首先是名字出错&#xff0c;不知为何gitee任意把我的名字更改。 导致无法push验证 git push -u origin "master 显示&#xff1a;fatal: Authentication failed for https://gitee.com/zhang-great/stm32-smart-security-system.git/ 我…...

小程序事件系统 —— 32 事件系统 - 事件分类以及阻止事件冒泡

在微信小程序中&#xff0c;事件分为 冒泡事件 和 非冒泡事件 &#xff1a; 冒泡事件&#xff1a;当一个组件的事件被触发后&#xff0c;该事件会向父节点传递&#xff1b;&#xff08;如果父节点中也绑定了一个事件&#xff0c;父节点事件也会被触发&#xff0c;也就是说子组…...

‌PLC数据类型和‌C#数据类型的数据类型映射表

数据类型映射表 ‌PLC数据类型‌C#数据类型读取方式‌补充说明BitboolDBX布尔值BytebyteDBB单字节无符号整数WordushortDBW16位无符号整数DWorduintDBD32位无符号整数Intshort16位有符号整数DIntint32位有符号整数RealfloatDBR单精度浮点数LRealdoubleDBL双精度浮点数Stringstr…...

全球首创!微软发布医疗AI助手,终结手写病历时代

今天凌晨&#xff0c;微软发布了医疗界首个用于临床工作流程的AI助手Microsoft Dragon Copilot。 Dragon Copilot是基于语音文本的混合架构&#xff0c;能够将医生的语音或临床口述内容实时转换为文本。例如&#xff0c;医生可以通过语音输入患者的病历信息、医嘱或诊断结果&a…...

每日一题----------异常处理

总结&#xff1a; NullPointerException&#xff1a;尝试使用一个空引用进行操作时抛出。 ArrayIndexOutOfBoundsException&#xff1a;数组下标越界时抛出。 ClassCastException&#xff1a;类型转换失败时抛出。 ArithmeticException&#xff1a;数学运算错误时抛出&#…...

HTML 属性(详细易懂)

HTML&#xff08;超文本标记语言&#xff09;是用于创建网页和其他可在浏览器中查看的内容的基础标记语言。HTML 属性是 HTML 元素的额外信息&#xff0c;它们提供了元素的更多细节&#xff0c;如元素的标识符、样式、行为等。在本文中&#xff0c;将详细介绍 HTML 属性&#x…...

基于火山引擎的DeepSeek-V3 api实现简单的数据查询功能

前言 现在ai比较火&#xff0c;ai可以极大的提高大家的工作效率&#xff0c;所以有空的话要学习下ai的使用 火山引擎大模型 火山引擎大模型广场&#xff0c;聚集了市面上常见的基座大模型&#xff0c;每个模型都有50Wtokens的免费调用量&#xff0c;可以方便大家调用 账号登…...

AI入门1:关键概念

1. 基础概念 ​AI&#xff08;Artificial Intelligence&#xff0c;人工智能&#xff09;​ 模拟人类智能的机器系统&#xff0c;具备学习、推理、决策等能力。 ​Machine Learning&#xff08;机器学习&#xff0c;ML&#xff09;​ 让计算机通过数据自动学习规律&#xff0c…...

WPS工具栏添加Mathtype加载项

问题描述&#xff1a; 分别安装好WPS和MathType之后&#xff0c;WPS工具栏没直接显示MathType工具&#xff0c;或者是前期使用正常&#xff0c;由于WPS更新之后MathType工具消失&#xff0c;如下图 解决办法 将文件“MathType Commands 2016.dotm”和“MathPage.wll”从Matht…...

【MySQL-数据类型】数据类型分类+数值类型+文本、二进制类型+String类型

一、数据类型分类 二、数值类型 1.bit类型 测试环境ubuntu 基本语法&#xff1a; bit[(M)]&#xff1a;位字段类型&#xff0c;M表示每个值的位数&#xff0c;范围从1&#xff5e;64&#xff1b;如果M被忽略&#xff0c;默认为1举例&#xff1a; create table testBit(id i…...

cuda矩阵转置算子(共享内存)

cpu版本 即为按行遍历行列互换 // 主机上的矩阵转置函数&#xff0c;用于验证结果 void cpuTranspose(const float *input, float *output, int n) {for (int row 0; row < n; row){for (int col 0; col < n; col){output[col * n row] input[row * n col];}} }gp…...

GB28181视频监控流媒体平台LiveGBS如何自定义收流端口区间以便减少收流端口数或解决端口冲突问题

LiveGBS GB28181流媒体服务在接收视频的时候默认是使用30000-30249&#xff0c; webrtc流播放端口区间默认是UDP的30250-30500区间。有些网络环境不方便开放这么大的端口区间&#xff0c;下面介绍下如何修改配置这个区间。 从页面上修改这个区间&#xff0c;端口区间尽量设置大…...

在Go语言中,判断变量是否为“空”(零值或未初始化状态)的方法总结

在Go语言中,判断变量是否为“空”(零值或未初始化状态)的方法因数据类型而异。以下是各类型变量的判断方法总结: 1. 基本类型 整数(int) 判断是否等于零值 0。 var i int if i == 0 { // 空 } 字符串(string) 判断是否等于空字符串 ""。 var s string if s =…...

VUE3开发-9、axios前后端跨域问题解决方案

VUE前端解决跨域问题 前端页面需要改写 如果无效&#xff0c;记得重启服务器 后端c#解决跨域问题 前端js取值&#xff0c;后端c#跨域_c# js跨域-CSDN博客...

利用 requestrepo 工具验证 XML外部实体注入漏洞

1. 前言 在数字化浪潮席卷的当下&#xff0c;网络安全的重要性愈发凸显。应用程序在便捷生活与工作的同时&#xff0c;也可能暗藏安全风险。XXE&#xff08;XML外部实体&#xff09;漏洞作为其中的典型代表&#xff0c;攻击者一旦利用它&#xff0c;便能窃取敏感信息、掌控服务…...

嵌入式开发之串行数据处理

前题 前面几篇文章写了关于嵌入式软件开发时&#xff0c;关于串行数据处理的一些相关内容&#xff0c;有兴趣的可以看看《嵌入式开发&#xff1a;软件架构、驱动开发与串行数据处理》、《嵌入式软件开发之生产关系模型》和《嵌入式开发之Modbus-RTU协议解析》相关的内容。从业十…...

深入解析 JVM —— 从基础概念到实战调优的全链路学习指南

文章目录 一、为什么要学习 JVM&#xff1f;1. 面试必备与技能提升2. 性能优化与问题诊断3. 编写高质量代码 二、JVM 基础概念与体系结构1. JVM 简介2. JDK、JRE 与 JVM 三、JVM 内存模型1. 线程私有区2. 线程共享区 四、类加载机制与双亲委派1. 类加载过程2. 双亲委派模型3. 动…...

LTC6804、LTC6811、LTC6813的使用

FSEC自制BMS第一步&#xff1a;从零开发使用LTC6804采集电池电压 LTC6811特性 LTC6811 是 LTC6804 的引脚兼容型升级器件&#xff0c;LTC6804官方已经不推荐选用 可测量多达 12 节串联电池 1.2mV 最大总测量误差 可堆叠式架构能支持几百个电池 内置 isoSPI™ 接口 可在 290μ…...

Spring 构造器注入和setter注入的比较

一、比较说明 在 Spring 框架中&#xff0c;构造器注入&#xff08;Constructor Injection&#xff09;和 Setter 注入&#xff08;Setter Injection&#xff09;是实现依赖注入&#xff08;DI&#xff09;的两种主要方式。它们的核心区别在于依赖注入的时机、代码设计理念以及…...

【LangChain】对话历史管理

1 历史记录的剪裁 trimmed_messages from langchain_core.messages import (AIMessage,HumanMessage,SystemMessage,trim_messages, ) from langchain_openai import ChatOpenAImessages [SystemMessage("youre a good assistant, you always respond with a joke."…...

【无人机三维路径规划】基于CPO冠豪猪优化算法的无人机三维路径规划Maltab

代码获取基于CPO冠豪猪优化算法的无人机三维路径规划Maltab 基于CPO冠豪猪优化算法的无人机三维路径规划 一、CPO算法的基本原理与核心优势 冠豪猪优化算法&#xff08;Crested Porcupine Optimizer, CPO&#xff09;是一种新型元启发式算法&#xff0c;其灵感来源于冠豪猪的…...

CAN协议介绍

目录 一、CAN协议 1.1 CAN协议简介 1.2 CAN物理层 1.3 CAN协议层 二、CAN控制器 2.1 CAN控制内核 2.2 CAN发送邮箱 2.3 CAN接收FIFO 2.4 CAN验收筛选器 一、CAN协议 1.1 CAN协议简介 CAN 是控制器局域网络 (Controller Area Network) 的简称&#xff0c;它是由研发和生…...

树莓派 Interface Option 中没有camera选项

最近重温树莓派的视觉&#xff0c;烧录了树莓派的新系统后发现在 raspi-config 中的 Interface Option 没有 camera 选项&#xff0c;同时在终端用 vcgencmd get_camera 查看摄像头时没有检测到树莓派的 CSI 摄像头&#xff0c;在 Thonny 中调用树莓派摄像头出现报错&#xff1…...

大数据学习(55)-BI工具数据分析的使用

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…...

轻松上手 —— 通过 RPM 包快速部署 NebulaGraph

前言 在当今大数据时代&#xff0c;处理复杂关系数据的需求与日俱增&#xff0c;图数据库应运而生并逐渐崭露头角。NebulaGraph 作为一款高性能、分布式且易扩展的图数据库&#xff0c;专为应对大规模图数据处理而精心打造。它不仅具备丰富的查询语言&#xff0c;还拥有强大高效…...

nginx作为下载服务器配置

一、Nginx 作为下载服务器配置笔记 基本配置指令 server块配置&#xff1a; 在 Nginx 的配置文件&#xff08;通常是/etc/nginx/nginx.conf或在/etc/nginx/conf.d/目录下的特定配置文件&#xff09;中&#xff0c;首先需要定义一个server块来监听特定的端口并处理下载请求。例如…...

第六课:数据存储三剑客:CSV/JSON/MySQL

在Python的数据存储与处理领域&#xff0c;CSV、JSON和MySQL被广大开发者誉为“数据存储三剑客”。它们各自在不同的场景下发挥着重要作用&#xff0c;无论是简单的数据交换、轻量级的数据存储&#xff0c;还是复杂的关系型数据库管理&#xff0c;都能找到它们的身影。本文将详…...

Dify 开源大语言模型应用开发平台使用(一)

文章目录 一、创建锂电池专业知识解答应用1.1 应用初始化二、核心功能模块详解2.1 知识库构建2.2 工作流与节点编排节点类型说明工作流设计示例:锂电池选型咨询2.3 变量管理三、测试与调试3.1 单元测试3.2 压力测试3.3 安全验证四、部署与优化建议4.1 部署配置4.2 持续优化结论…...

PyQt高亮代码

PyQt高亮代码 安装 Pygments支持的格式支持的样式详解参考 Qt中使用 安装 Pygments Pygments 是Python中的一个高亮代码的包&#xff0c;挺好用的 pip install Pygments支持的格式 支持的格式比较多&#xff0c;不列出来了 # coding:utf-8 from pygments.lexers import get_all…...

小白学Agent技术[1]

文章目录 课程地址Agent介绍原理架构任务规划记忆工具使用程序开发范式的变化Agent开发注意事项 课程地址 Agent课程地址 Agent介绍 AI Agent&#xff08;人工智能代理、AI智能体&#xff09;&#xff0c;一种模拟人类智能行为的人工智能系统&#xff0c;以大模型语言&#…...

以商业思维框架为帆,驭创业浪潮前行

创业者踏入商海&#xff0c;如同航海家奔赴未知海域&#xff0c;需有清晰的思维罗盘指引方向。图中“为什么—用什么—怎么做—何人做—投入产出”的商业框架&#xff0c;正是创业者破解商业谜题的密钥&#xff0c;从需求洞察到落地执行&#xff0c;为创业之路铺就逻辑基石。 …...

开源宝藏 Tigshop,开启电商新征程

在电商竞争愈发激烈的当下&#xff0c;一个强大且适配的商城系统是商家制胜的法宝。 Tigshop官网&#xff1a;Tigshop官网 - 开源商城系统Tigshop开源商城系统&#xff0c;支持b2b2c、多商户、多店铺、商家入驻、分销系统、跨境电商、连锁商城等解决方案&#xff0c;免费下载&…...

java多线程实现方式

目录 1. 继承 Thread 类 2. 实现 Runnable 接口 3. 实现 Callable 接口 4. 使用线程池 5. 使用 CompletableFuture&#xff08;Java 8&#xff09; 6. 使用 ForkJoinPool&#xff08;Java 7&#xff09; 7. 使用 Timer 和 TimerTask 8. 使用 ScheduledExecutorService …...

windows:curl: (60) schannel: SEC_E_UNTRUSTED_ROOT (0x80090325)

目录 1. git update-git-for-windows 报错2. 解决方案2.1. 更新 CA 证书库2.2. 使用 SSH 连接&#xff08;推荐&#xff09;2.3 禁用 SSL 验证&#xff08;不推荐&#xff09; 1. git update-git-for-windows 报错 LenovoLAPTOP-EQKBL89E MINGW64 /d/YHProjects/omni-channel-…...

python:pymunk + pygame 模拟六边形内小球弹跳运动

向 chat.deepseek.com 提问&#xff1a;编写 python 程序&#xff0c;用 pymunk, 有一个正六边形&#xff0c;围绕中心点缓慢旋转&#xff0c;六边形内有一个小球&#xff0c;六边形的6条边作为墙壁&#xff0c;小球受重力和摩擦力、弹力影响&#xff0c;模拟小球弹跳运动&…...

vulnhub靶场之【digitalworld.local系列】的vengeance靶机

前言 靶机&#xff1a;digitalworld.local-vengeance&#xff0c;IP地址为192.168.10.10 攻击&#xff1a;kali&#xff0c;IP地址为192.168.10.6 kali采用VMware虚拟机&#xff0c;靶机选择使用VMware打开文件&#xff0c;都选择桥接网络 这里官方给的有两种方式&#xff…...

shiro550-cve-2016-4437复现

shiro550-cve-2016-4437 复现环境&#xff1a;docker desktop idea远程调试jdk版本必须与容器里的jdk1.8.0_102 匹配上&#xff0c;下载资源翻我CC1链那篇文章 注意burpsuite的proxy listeners端口改一下别跟docker容器的重了。 ysoserial工具&#xff1a;https://github.c…...

【DeepSeek】Ubuntu快速部署DeepSeek(Ollama方式)

文章目录 人人都该学习的DeepSeekDeepSeek不同版本功能差异DeepSeek与硬件直接的关系DeepSeek系统兼容性部署方式选择部署步骤&#xff08;Ollama方式&#xff09;1.选定适合的deepseek版本2.环境准备3.安装Ollama4.部署deepseek5.测试使用 人人都该学习的DeepSeek DeepSeek 作…...

Windows 版本Nmap使用报错“无法打开device eth0”

背景 使用nmap在win10上进行扫描工作正常&#xff0c;换到win server 2012 r2以后&#xff0c;扫描报错“无法打开device eth0” 使用了重装、重启大法&#xff0c;未彻底解决 PS&#xff1a;这台服务器之前完装过wireshark&#xff0c;实际已经安装了npcap 解决步骤 查询了…...

java字符串

字符串构造 1.使用常量串构造 String h1 "hello";System.out.println(h1); 2.new对象 String h2 new String("hello");System.out.println(h2); 3.使用字符数组构造 char[] array {h,e,l,l,o};String h3 new String(array);System.out.println(h3);…...

Uniapp 页面返回不刷新?两种方法防止 onShow 触发多次请求!

目录 前言1. 变量&#xff08;不生效&#xff09;2. 延迟&#xff08;生效&#xff09; 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 在 Uniapp 中&#xff0c;使用 onShow() 钩子来监听页面显示&#xff0…...

鸿蒙生态日日新,夸克、顺丰速运、驾校一点通等多款应用功能更新

3月5日鸿蒙生态日日新PLOG&#xff1a;吉事办、健康甘肃等政务服务App上架原生鸿蒙应用市场&#xff1b;夸克、顺丰速运、驾校一点通等多款应用功能更新。...

库制作与原理

什么是库 库是写好的现有的&#xff0c;成熟的&#xff0c;可以复用的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能每个人的代码都从零开始&#xff0c;因此库的存在意义非同寻常。本质上来说库是一种可执行代码的二进制形式&#xff0c;可以被操作系统载入…...

《量子Java:从超导芯片到光子计算的编程革命》——解析Google量子AI中心的混合架构,揭秘如何用Java控制量子比特!

标题:《量子Java:从超导芯片到光子计算的编程革命》——解析Google量子AI中心的混合架构,揭秘如何用Java控制量子比特! 引言:当Java代码撞上量子叠加态——Google量子AI中心的0.003秒奇迹 Google量子AI中心首次实现Java程序对1200量子比特光量子芯片的实时控制,仅耗时3毫…...