聊聊Spring AI Alibaba的YoutubeDocumentReader
序
本文主要研究一下Spring AI Alibaba的YoutubeDocumentReader
YoutubeDocumentReader
community/document-readers/spring-ai-alibaba-starter-document-reader-youtube/src/main/java/com/alibaba/cloud/ai/reader/youtube/YoutubeDocumentReader.java
public class YoutubeDocumentReader implements DocumentReader {private static final String WATCH_URL = "https://www.youtube.com/watch?v=%s";private final ObjectMapper objectMapper;private static final List<String> YOUTUBE_URL_PATTERNS = List.of("youtube\\.com/watch\\?v=([^&]+)","youtu\\.be/([^?&]+)");private final String resourcePath;private static final int MEMORY_SIZE = 5;private static final int BYTE_SIZE = 1024;private static final int MAX_MEMORY_SIZE = MEMORY_SIZE * BYTE_SIZE * BYTE_SIZE;private static final WebClient WEB_CLIENT = WebClient.builder().defaultHeader("Accept-Language", "en-US").codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(MAX_MEMORY_SIZE)).build();public YoutubeDocumentReader(String resourcePath) {Assert.hasText(resourcePath, "Query string must not be empty");this.resourcePath = resourcePath;this.objectMapper = new ObjectMapper();}@Overridepublic List<Document> get() {List<Document> documents = new ArrayList<>();try {String videoId = extractVideoIdFromUrl(resourcePath);String subtitleContent = getSubtitleInfo(videoId);documents.add(new Document(StringEscapeUtils.unescapeHtml4(subtitleContent)));}catch (IOException e) {throw new RuntimeException("Failed to load document from Youtube: {}", e);}return documents;}// Method to extract the videoId from the resourcePathpublic String extractVideoIdFromUrl(String resourcePath) {for (String pattern : YOUTUBE_URL_PATTERNS) {Pattern regexPattern = Pattern.compile(pattern);Matcher matcher = regexPattern.matcher(resourcePath);if (matcher.find()) {return matcher.group(1); // Extract the videoId (captured group)}}throw new IllegalArgumentException("Invalid YouTube URL: Unable to extract videoId.");}public String getSubtitleInfo(String videoId) throws IOException {// Step 1: Fetch the HTML content of the YouTube video pageString url = String.format(WATCH_URL, videoId);String htmlContent = fetchHtmlContent(url).block(); // Blocking for simplicity in// this example// Step 2: Extract the subtitle tracks from the HTMLString captionsJsonString = extractCaptionsJson(htmlContent);if (captionsJsonString != null) {JsonNode captionsJson = objectMapper.readTree(captionsJsonString);JsonNode captionTracks = captionsJson.path("playerCaptionsTracklistRenderer").path("captionTracks");// Check if captionTracks exists and is an arrayif (captionTracks.isArray()) {// Step 3: Extract and decode each subtitle track's URLStringBuilder subtitleInfo = new StringBuilder();JsonNode captionTrack = captionTracks.get(0);// Safely access languageCode and baseUrl with null checksString language = captionTrack.path("languageCode").asText("Unknown");String urlEncoded = captionTrack.path("baseUrl").asText("");// Decode the URL to avoid \u0026 issuesString decodedUrl = URLDecoder.decode(urlEncoded, StandardCharsets.UTF_8);String subtitleText = fetchSubtitleText(decodedUrl);subtitleInfo.append("Language: ").append(language).append("\n").append(subtitleText).append("\n\n");return subtitleInfo.toString();}else {return "No captions available.";}}else {return "No captions data found.";}}private Mono<String> fetchHtmlContent(String url) {// Use WebClient to fetch HTML content asynchronouslyreturn WEB_CLIENT.get().uri(url).retrieve().bodyToMono(String.class);}private String extractCaptionsJson(String htmlContent) {// Extract the captions JSON from the HTML contentString marker = "\"captions\":";int startIndex = htmlContent.indexOf(marker);if (startIndex != -1) {int endIndex = htmlContent.indexOf("\"videoDetails", startIndex);if (endIndex != -1) {String captionsJsonString = htmlContent.substring(startIndex + marker.length(), endIndex);return captionsJsonString.trim();}}return null;}private String fetchSubtitleText(String decodedUrl) throws IOException {// Fetch the subtitle text by making a request to the decoded subtitle URLorg.jsoup.nodes.Document doc = Jsoup.connect(decodedUrl).get();// Assuming the subtitle text is inside <transcript> tags, extract the textStringBuilder subtitleText = new StringBuilder();doc.select("text").forEach(textNode -> {String text = textNode.text();subtitleText.append(text).append("\n");});return subtitleText.toString();}}
YoutubeDocumentReader构造器要求输入resourcePath,它内置了WebClient,其get方法先通过extractVideoIdFromUrl获取videoId,再通过getSubtitleInfo获取字幕,最后组装为
List<Document>
返回;getSubtitleInfo通过请求https://www.youtube.com/watch?v=videoId
,之后解析html内容获取videoDetails内容,再json解析提取language、subtitleText
示例
community/document-readers/spring-ai-alibaba-starter-document-reader-youtube/src/test/java/com/alibaba/cloud/ai/reader/youtube/YoutubeDocumentReaderTest.java
public class YoutubeDocumentReaderTest {private static final Logger logger = LoggerFactory.getLogger(YoutubeDocumentReaderTest.class);@Testvoid youtubeDocumentReaderTest() {YoutubeDocumentReader youtubeDocumentReader = new YoutubeDocumentReader("https://www.youtube.com/watch?v=q-9wxg9tQRk");List<Document> documents = youtubeDocumentReader.get();logger.info("documents: {}", documents);}}
小结
spring-ai-alibaba-starter-document-reader-youtube提供了YoutubeDocumentReader,它通过webClient去请求指定url,提取字幕的language以及字幕内容,最后组装为List<Document>
返回。
doc
- java2ai
相关文章:
聊聊Spring AI Alibaba的YoutubeDocumentReader
序 本文主要研究一下Spring AI Alibaba的YoutubeDocumentReader YoutubeDocumentReader community/document-readers/spring-ai-alibaba-starter-document-reader-youtube/src/main/java/com/alibaba/cloud/ai/reader/youtube/YoutubeDocumentReader.java public class You…...
常用第三方库:flutter_boost混合开发
常用第三方库:flutter_boost混合开发 前言 在移动应用开发中,混合开发是一个非常重要的话题。特别是对于已有原生应用想要引入Flutter的团队来说,如何实现Flutter页面和原生页面的无缝整合就显得尤为关键。本文将深入介绍flutter_boost这个…...
什么是 JSON?学习JSON有什么用?在springboot项目里如何实现JSON的序列化和反序列化?
作为一个学习Javaweb的新手,理解JSON的序列化和反序列化非常重要,因为它在现代Web开发,特别是Spring Boot中无处不在。 什么是 JSON? 首先,我们简单了解一下JSON (JavaScript Object Notation)。 JSON 是一种轻量级的…...
[mysql]数据类型精讲
目录 数据类型精讲: 整数类型 浮点类型 日期和时间类型 文本字符串类型 数据类型精讲: 精度问题:不能损失数据 性能问题:表的设计,范式的讲解. 表设计的时候需要设置字段,我们现在要把字段类型讲完.,细节点一点点给大家拆解. Float和double是有精度的损失的,这边推荐使用…...
WordPress AI插件能自动写高质量文章吗,如何用AI提升网站流量
WordPress AI插件能自动写高质量文章吗? 最近很多站长都在问,用wordpress AI插件真的能写出搜索引擎喜欢的好文章吗?作为一个用过10款AI写作工具的老站长,今天我就来分享真实使用体验,告诉你哪些插件好用、怎么用才能…...
【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题)
【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题) 目录 【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题)一、历年真题二、考点:函数调用 —— 传值调用和传地址调用🔺1、传值调用🔺2、传引用(地址)调…...
ECMAScript 1(ES1):JavaScript 的开端
1. 版本背景与发布 ●发布时间:1997 年 6 月,由 ECMA International 正式发布,标准编号为 ECMA-262。 ●历史意义:ES1 是 JavaScript 的首个标准化版本,结束了 Netscape Navigator 与 Internet Explorer 浏览器间脚本语…...
C++入侵检测与网络攻防之暴力破解
目录 1.nessus扫描任务 2.漏洞信息共享平台 3.nessus扫描结果 4.漏扫报告的查看 5.暴力破解以及hydra的使用 6.crunch命令生成字典 7.其他方式获取字典 8.复习 9.关于暴力破解的防御的讨论 10.pam配置的讲解 11.pam弱密码保护 12.pam锁定账户 13.shadow文件的解析 …...
基于ssm的同城上门维修平台管理系统(源码+数据库)
54基于ssm的同城上门维修平台管理系统:前端jsp、jquery、bootstrap,后端 spring、mybatis,集成订单管理、商品管理、商品类型管理、商品浏览、购物车等功能于一体的系统。 ## 功能介绍 ### 用户 - 基本功能:登录、注册、退出、…...
力扣-hot100(和为k的子数组)
560. 和为 K 的子数组 中等 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1: 输入:nums [1,1,1], k 2 输出:2 示例 2: 输入…...
【计算机视觉】CV实战 - 基于YOLOv5的人脸检测与关键点定位系统深度解析
基于YOLOv5的人脸检测与关键点定位系统深度解析 1. 技术背景与项目意义传统方案的局限性YOLOv5多任务方案的优势 2. 核心算法原理网络架构改进关键点回归分支损失函数设计 3. 实战指南:从环境搭建到模型应用环境配置数据准备数据格式要求数据目录结构 模型训练配置文…...
HTML word属性
介绍 CSS word-spacing 属性,用于指定段字之间的空间,例如: p {word-spacing:30px; }word-spacing属性增加或减少字与字之间的空白。 注意: 负值是允许的。 浏览器支持 表格中的数字表示支持该属性的第一个浏览器版本号。 属…...
Java—ThreadLocal底层实现原理
首先,ThreadLocal 本身并不提供存储数据的功能,当我们操作 ThreadLocal 的时候,实际上操作线程对象的一个名为 threadLocals 成员变量。这个成员变量的类型是 ThreadLocal 的一个内部类 ThreadLocalMap,它是真正用来存储数据的容器…...
GTSRB德国交通标志数据集下载以及训练集划分
GTSRB德国交通标志数据集下载以及训练集划分 一、数据集下载二、数据集划分 一、数据集下载 官网地址:附含数据集说明文档点击下载:训练数据集点击下载:测试数据集 二、数据集划分 在模型训练时,将训练数据集分成训练集和验证集&…...
python 实现客户端软件许可证书签名授权 cryptography
目录 1.需求 2.cryptography介绍 3.实际代码 4.结束语 1.需求 采用pyside6开发了一款客户端软件, 为保护核心算法源码, 采用Nuitka打包python代码,这仅仅保护了核心算法代码,不能限制用户使用软件,因此需要软件许可授权签名证书ÿ…...
明远智睿SD2351核心板:以48元撬动AI视觉产业革命的“硬核引擎”
在人工智能浪潮席卷全球的今天,AI视觉作为连接虚拟与现实的“智慧之眼”,正以惊人的速度重塑着产业格局。从智慧城市中的安防监控到自动驾驶汽车的“视觉神经”,从工业产线的缺陷检测到家庭场景的智能管家,AI视觉技术的每一次突破…...
【C语言】全局变量、静态本地变量
在C语言中,变量是存储数据的基本单元。 不同类型的变量有着不同的特性和用途,其中全局变量和本地变量是比较特殊且重要的两类变量。 一、全部变量 1.1 全局变量的作用域和生存期 全局变量是在函数外部定义的变量,其作用域从定义的位置开始&…...
32.768kHz晶振详解:作用、特性及与其他晶振的区别
一、32.768kHz晶振的核心作用 实时时钟(RTC)驱动: 提供精确的1Hz时钟信号,用于计时功能(如电子表、计算机CMOS时钟)。 分频公式: 1Hz 32.768kHz / 2^15(通过15级二分频实现&#x…...
classfinal 修改过源码,支持jdk17 + spring boot 3.2.8
先贴图 使用 classfinal 修改过源码 支持jdk17 spring boot 3.3.0 使用方式: 1、springboot的jar加密 java -jar classfinal-fatjar-1.2.1.jar -file MySpringBoot.jar -libjars my-common.jar -packages cn.com.cmd -pwd 123456 -Y 得到: MySpri…...
算法训练营 Day1
努力追上那个曾经被寄予厚望的自己 —— 25.4.25 一、LeetCode_26 删除有序数组中的重复项 给你⼀个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现⼀次 ,返回删除后数组的 新⻓度。元素的 相对顺序 应该保持 ⼀致 …...
4/25 研0学习日志
Python学习 python 4个常用的数据容器 list dict tuple set list 列表中数据类型可以不一样 构造方式 mylist["xxx","xxxx"] 获取数据方式 mylist[1] mylist[:4] mylist[-1:] 添加数据 mylist.append() mylist.extern(["aaa","aaaa&…...
手机打电话时电脑坐席同时收听对方说话并插入IVR预录声音片段
手机打电话时电脑坐席同时收听对方说话并插入IVR预录声音片段 --本地AI电话机器人 前言 书接上一篇,《手机打电话通话时如何向对方播放录制的IVR引导词声音》中介绍了【蓝牙电话SDK示例App】可以实现手机app在电话通话过程中插播预先录制的开场白等语音片段的功能。…...
汽车零配件供应商如何通过EDI与主机厂生产采购流程结合
当前,全球汽车产业正经历深刻的数字化转型,供应链协同模式迎来全新变革。作为产业链核心环节,汽车零部件供应商与主机厂的高效对接已成为企业发展的战略要务。然而,面对主机厂日益严格的数字化采购要求,许多供应商在ED…...
sql server 开启cdc报事务正在执行
今天开启数据库cdc 功能的时候提示:一个dbrole 的存储过程,rolemember cdc db_ower, ,有事务正在进行,执行失败。 执行多次仍然如此,开启cdc的存储过程是sys.sp_cdc_enable_db;查询了一下网络,给出的方…...
03实战篇Redis02(优惠卷秒杀、分布式锁)
3、优惠卷秒杀 3.1 -全局唯一ID 每个店铺都可以发布优惠券: 当用户抢购时,就会生成订单并保存到tb_voucher_order这张表中,而订单表如果使用数据库自增ID就存在一些问题: id的规律性太明显 受单表数据量的限制 场景分析&…...
ECharts 地图开发入门
一、准备工作:环境搭建与数据准备 1. 引入 ECharts 库 TypeScript 取消自动换行复制 <!-- 引入 ECharts 核心库 --> <script src"https://cdn.jsdelivr.net/npm/echarts5.4.0/dist/echarts.min.js"></script> <!-…...
机器学习基础 - 回归模型之线性回归
机器学习: 线性回归 文章目录 机器学习: 线性回归1. 线性回归1. 简介2. 线性回归如何训练?1. 损失函数2. 正规方程3. 梯度下降法4. 两种方法的比较2. 岭回归岭回归与线性回归3. Lasso 回归4. ElasticNet 回归LWR - 局部加权回归QA1. 最小二乘法估计2. 最小二乘法的几何解释3…...
《解锁LLMs from scratch:开启大语言模型的探索之旅》
《解锁LLMs from scratch:开启大语言模型的探索之旅》 GitHub - datawhalechina/llms-from-scratch-cn: 仅需Python基础,从0构建大语言模型;从0逐步构建GLM4\Llama3\RWKV6, 深入理解大模型原理 项目首页 - LLMs-from-scratch:从零开始逐步指导开发者构建自己的大型语言模型…...
嵌入式 C 语言面试核心知识点全面解析:基础语法、运算符与实战技巧
在嵌入式面试中,C 语言基础是重中之重。本文针对经典面试题进行详细解析,帮助新手系统掌握知识点,提升面试应对能力。 一、数据结构逻辑分类 题目 在数据结构中,从逻辑上可以把数据结构分为( )。 A、动态…...
pyqt中以鼠标所在位置为锚点缩放图片
在编写涉及到图片缩放的pyqt程序时,如果以鼠标为锚点缩放图片,图片上处于鼠标所在位置的点(通常也是用户关注的图片上的点)不会移动,更不会消失在图片显示区域之外,可以提高用户体验,是一个值得…...
登高架设作业证考试的实操项目有哪些?
登高架设作业证考试的实操项目分为 4 个科目,包括安全防护用品使用、作业现场安全隐患排除、安全操作技术、作业现场应急处置,具体内容如下: 科目一:安全防护用品使用(K1) 考试项目:安全帽、安全…...
闻性与空性:从耳根圆通到究竟解脱的禅修路径
一、闻性之不动:超越动静的觉性本质 在《楞严经》中,佛陀以钟声为喻揭示闻性的奥秘:钟声起时,闻性显现;钟声歇时,闻性不灭。此“不动”并非如磐石般凝固,而是指觉性本身超越生灭、来去的绝对性…...
404了怎么办快把路由给我断掉(React配置路由)
路由基础概念 什么是前端路由? 核心作用:管理单页面应用的页面切换主要功能: 根据URL显示对应组件 保持浏览器历史记录 实现页面间导航不刷新 React Router 包含三个主要包: react-router:核心逻辑react-router-d…...
React类组件与React Hooks写法对比
React 类组件 vs Hooks 写法对比 分类类组件(Class Components)函数组件 Hooks组件定义class Component extends React.Componentconst Component () > {}状态管理this.state this.setState()useState()生命周期componentDidMount, componentDidU…...
Tailwind CSS实战:快速构建定制化UI的新思路
引言 在当今快节奏的前端开发环境中,开发者不断寻找能够提高效率并保持灵活性的工具。Tailwind CSS作为一个功能型优先的CSS框架,正在改变开发者构建用户界面的方式。与Bootstrap和Material UI等传统组件库不同,Tailwind不提供预设组件&…...
告别手动映射:在 Spring Boot 3 中优雅集成 MapStruct
在日常的后端开发中,我们经常需要在不同的对象之间进行数据转换,例如将数据库实体(Entity)转换为数据传输对象(DTO)发送给前端,或者将接收到的 DTO 转换为实体进行业务处理或持久化。手动进行这…...
JavaScript学习教程,从入门到精通,Ajax数据交换格式与跨域处理(26)
Ajax数据交换格式与跨域处理 一、Ajax数据交换格式 1. XML (eXtensible Markup Language) XML是一种标记语言,类似于HTML但更加灵活,允许用户自定义标签。 特点: 可扩展性强结构清晰数据与表现分离文件体积相对较大 示例代码࿱…...
抖音IP属地跟无线网有关系吗?一文解析
在抖音等社交平台上,IP属地显示功能让许多用户感到好奇——为什么自己的位置信息有时准确,有时却显示在其他城市?这时,用户会疑惑:抖音IP属地跟无线网有关系吗?本文将详细解析IP属地和无线网的概念…...
RDK X3新玩法:超沉浸下棋机器人开发日记
一、项目介绍 产品中文名:超沉浸式智能移动下棋机器人 产品英文名:Hackathon-TTT 产品概念:本项目研发的下棋机器人,是一款能自主移动、具备语音交互并能和玩家在真实的棋盘上进行“人机博弈”的移动下棋平台,能够带给…...
Trae 实测:AI 助力前端开发,替代工具还远吗?
Trae 实测:AI 助力前端开发,替代工具还远吗? 字节上线了一款 AI 新产品,名叫 Trae 。这是一款 IDE 工具,中文意思是「集成开发环境」,做技术的读者对此应该很熟悉。简单理解,就是程序员用来写代…...
SpringCloud基于Eureka和Feign实现一个微服务系统
Spring Cloud 是基于 Spring Boot 的 微服务开发全栈解决方案,通过集成多种开源组件,提供分布式系统构建所需的服务治理、配置管理、容错机制等核心能力,简化微服务架构的复杂性。其核心目标是实现服务间的高效协同与弹性伸缩,支撑企业级云原生应用开发。Spring Clou…...
nacos设置权重进行负载均衡不生效
nacos设置权重进行负载均衡不生效,必须在启动类下加上这个bean Beanpublic IRule nacosRule(){return new NacosRule();}如下图所示...
Flowable7.x学习笔记(十四)查看部署流程Bpmn2.0-xml
前言 Flowable 在其前端 Modeler 中,采用 BPMN 2.0 标准将流程中的任务、网关、事件等元素以 XML 形式存储,并附带图形互换(Diagram Interchange,DI)数据,以保证在前端与后端都能精准重建可视化流程图。 生…...
大模型应用中Agent2Agent(A2A)的应用场景,以及A2A与MCP的区别和适用场景
大家好,我是微学AI,今天给大家介绍一下大模型应用中Agent2Agent(A2A)的应用场景,以及A2A与MCP的区别和适用场景。 文章目录 一、引言二、Agent2Agent(A2A)协议原理2.1 核心架构2.2 基础框架与依…...
Windows server:
企鹅裙:429603659 域搭建 (细节上的问题) 1.将IP地址修改为静态IP,搭建完后设置DNS为本身(在搭建完域服务器后设置DNS) 2.配置之前需将计算机名更改为后面题目中所要求的. 3.一些版本之中比如Windows Server2012之中搭建域之后重启会显示…...
Python 3.14:探索新版本的魅力与革新
在Python编程语言的不断演进中,Python 3.14作为又一重要里程碑,承载着开发者们的期待与热情,悄然走进了我们的视野。尽管在撰写本文时,Python 3.14可能尚未正式成为主流版本(注:实际发布情况需根据最新信息…...
LabVIEW基于VI Server的控件引用操作
本 VI 通过展示控件引用(Control References)的使用,借助 VI Server 实现对前面板对象的编程操作。 详细说明 隐式属性节点(Implicitly Linked Property Node):通过右键单击控件(或其控件终…...
【不同名字的yolo的yaml文件名是什么意思】
以下是这些 YOLO 系列配置文件的详细解析,按版本和功能分类说明: 一、YOLOv3 系列 文件名核心特性适用场景yolov3.yaml原始 YOLOv3 结构,3 尺度预测(13x13,26x26,52x52)通用目标检测yolov3-spp.yaml增加 SPPÿ…...
《100天精通Python——基础篇 2025 第3天:变量与数据类型全面解析,掌握Python核心语法》
目录 一、Python变量的定义和使用二、Python整数类型(int)详解三、Python小数/浮点数(float)类型详解四、Python复数类型(complex)详解---了解五、Python字符串详解(包含长字符串和原始字符串)5.1 处理字符串中的引号5.2 字符串的…...
精益数据分析(24/126):聚焦第一关键指标,驱动创业成功
精益数据分析(24/126):聚焦第一关键指标,驱动创业成功 在创业和数据分析的探索之旅中,我们都在不断寻找能够助力成功的关键因素。今天,我依旧带着与大家共同进步的初心,深入解读《精益数据分析…...