B站缓存视频数据m4s转mp4

B站缓存视频数据m4s转mp4

  • 结构分析

结构分析

在没有改变数据存储目录的情况下,b站默认数据保存目录为:
`Android->data->tv.danmaku.bili->download`

在这里插入图片描述
每个文件夹代表一个集合的视频,比如,我下载的”java从入门到精通“,那么就会保存到一个目录里面:
在这里插入图片描述
每个以c_开头的都是一个小章节。
在这里插入图片描述
每个小章节包含entry.json(视频标题及章节名称等信息),danmaku.xml(弹幕),64或80等(视频文件及音频文件等)
在这里插入图片描述
将audio.m4s以及video.m4s合成后就是一个完整的视频。本地得安装ffmpeg或者使用python-ffmpeg。
关键部分代码:

command = ["ffmpeg","-i", video_m4s,  # 输入视频文件"-i", audio_m4s,  # 输入音频文件'-c:v', 'copy',  # 不重新编码视频'-c:a', 'copy',  # 不重新编码音频"-y",  # 覆盖已存在的文件output_mp4  # 输出文件]# 使用 subprocess.run 执行命令result = subprocess.run(command)

将整个标题的视频转换出来。

#!/usr/bin/python3
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
import subprocess
import os
import json
import ffmpegdef select_source():# 选择视频源目录dir_path = filedialog.askdirectory(title="选择视频源目录")if dir_path:source_entry.delete(0, END)source_entry.insert(0, dir_path)def select_target():# 选择保存目录dir_path = filedialog.askdirectory(title="选择视频保存目录")if dir_path:target_entry.delete(0, END)target_entry.insert(0, dir_path)def convert_with_ffmpeg(video_m4s, audio_m4s, output_mp4):if os.path.getsize(video_m4s) < 0 or os.path.getsize(audio_m4s) <= 0:print("非法的音视频文件,{audio_m4s},视频文件:{video_m4s}")return Falsetry:# 输入视频和音频video = ffmpeg.input(video_m4s)audio = ffmpeg.input(audio_m4s)# 构造 FFmpeg 命令command = ["ffmpeg","-i", video_m4s,  # 输入视频文件"-i", audio_m4s,  # 输入音频文件'-c:v', 'copy',  # 不重新编码视频'-c:a', 'copy',  # 不重新编码音频"-y",  # 覆盖已存在的文件output_mp4  # 输出文件]# 使用 subprocess.run 执行命令result = subprocess.run(command)# 检查命令是否成功执行if result.returncode == 0:print(f"{output_mp4} -> 合并成功!")return Trueelse:print(f"合并失败, 视频文件:{video_m4s}, 音频文件:{audio_m4s}")print(f"错误信息: {result.stderr}")return Falseexcept ffmpeg.Error as e:print(f"合并失败,音频文件:{audio_m4s},视频文件:{video_m4s}")return Falsedef batch_convert_vedio(source_path, target_path):for dir in os.listdir(source_path):dir_path = os.path.join(source_path, dir)entry_file = os.path.join(dir_path, "entry.json")data_dir = os.listdir(dir_path).pop(0)audio_path = os.path.join(dir_path, data_dir, "audio.m4s")vedio_path = os.path.join(dir_path, data_dir, "video.m4s")with open(entry_file, 'r', encoding='utf-8') as f:entry_sjon = f.read()json_data = json.loads(entry_sjon)part_content = json_data.get("page_data", {}).get("part")title = json_data.get("title")if not os.path.exists(os.path.join(target_path, f'{title}')):os.makedirs(os.path.join(target_path, f'{title}'))target_vedio_path = os.path.join(target_path, f'{title}/{part_content}.mp4')convert_with_ffmpeg(vedio_path, audio_path, target_vedio_path)print(target_vedio_path)def convert_video():source_path = source_entry.get()target_path = target_entry.get()if not source_path or not target_path:messagebox.showerror("错误", "请选择源目录和目标目录!")else:batch_convert_vedio(source_path, target_path)messagebox.showinfo("成功", f"视频将从 {source_path} 转换保存到 {target_path}")root = Tk()
root.title("bili视频转换工具")# 设置窗口大小并居中
window_width = 500  # 稍微加宽窗口
window_height = 200
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
x = (screen_width - window_width) // 2
y = (screen_height - window_height) // 2
root.geometry(f"{window_width}x{window_height}+{x}+{y}")# 配置网格布局权重
for i in range(5):root.grid_columnconfigure(i, weight=1)
for i in range(4):root.grid_rowconfigure(i, weight=1)# 视频源目录选择
source_label = Label(root, text="视频源目录:")
source_label.grid(row=0, column=0, sticky="e", padx=5, pady=5)source_entry = Entry(root)
source_entry.grid(row=0, column=1, columnspan=3, sticky="ew", padx=5, pady=5)source_button = Button(root, text="浏览...", command=select_source)
source_button.grid(row=0, column=4, sticky="ew", padx=5, pady=5)# 视频保存目录选择
target_label = Label(root, text="视频保存目录:")
target_label.grid(row=1, column=0, sticky="e", padx=5, pady=5)target_entry = Entry(root)
target_entry.grid(row=1, column=1, columnspan=3, sticky="ew", padx=5, pady=5)target_button = Button(root, text="浏览...", command=select_target)
target_button.grid(row=1, column=4, sticky="ew", padx=5, pady=5)# 转换按钮
button_convert = Button(root, text="立即转换", command=convert_video)
button_convert.grid(row=2, column=1, columnspan=3, sticky="ew", padx=50, pady=20)# 进入消息循环
root.mainloop()

具体效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

一次Oracle的非正常关闭

数据库自己会关闭吗&#xff1f; 从现象来说Oracle MySQL Redis等都会出现进程意外停止的情况。而这些停止都是非人为正常关闭或者暴力关闭&#xff08;abort或者kill 进程&#xff09; 一次测试环境的非关闭 一般遇到这种情况先看一下错误日志吧。 2025-06-01T06:26:06.35…

linux 串口调试命令 stty

linux 串口调试命令 stty 文章目录 linux 串口调试命令 sttystty 常见命令选项&#xff1a;常用参数&#xff1a;一次性设置串口所有常见参数总结 stty&#xff08;设置终端行模式&#xff09;命令是用来配置终端设备&#xff08;包括串口设备&#xff09;的输入和输出行为的工…

【地址区间划分】

地址区间划分 1 decode_addr1.1 地址区间1.2 变式 本篇博客主要介绍对地址区间划分的一个比较巧妙参数化的做法。 1 decode_addr 遇到一个master转多个slave时&#xff0c;不可避免需要进行对addr总线进行分配地址区间来进行选中&#xff1b; 在这里给出一个可复用且设计思想比…

mysql复合查询mysql子查询

基础表结构创建 表结构包含主外键约束和字符集配置&#xff0c;确保数据完整性 部门表 CREATE TABLE dept (deptno int NOT NULL COMMENT 部门编号,dname varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 部门名称,loc varchar(20) CHARACTE…

vlan(虚拟局域网)逻辑图解+实验详解

VLAN&#xff08;Virtual Local Area Network&#xff0c;虚拟局域网&#xff09; 是一种通过逻辑方式&#xff08;非物理连接&#xff09;将网络设备划分为多个独立广播域的技术。它允许管理员在同一个物理网络中创建多个隔离的虚拟网络&#xff0c;从而提升网络的安全性、灵…

2025年—Comfy UI 和 Stable Diffusion底层原理

为什么要先讲SD原理 &#xff1f; 逻辑理解: ComfyUI是节点式操作&#xff0c;需要自行搭建工作流&#xff0c;理解原理才能灵活定制工作流学习效率: 基础原理不懂会导致后续学习吃力&#xff0c;原理是掌握ComfyUI的关键核心价值: ComfyUI最有价值的功能就是自主搭建工作流&a…

深入理解C#中的Web API:构建现代化HTTP服务的完整指南

在当今的软件开发领域&#xff0c;构建高效、可扩展的Web服务已成为一项基本需求。作为.NET开发者&#xff0c;C#中的Web API框架为我们提供了创建RESTful服务的强大工具。本文将全面探讨Web API的核心概念、实现细节和最佳实践&#xff0c;帮助您掌握这一关键技术。 一、Web A…

起重机指挥人员在工作中需要注意哪些安全事项?

起重机指挥人员在作业中承担着协调设备运行、保障作业安全的关键职责&#xff0c;其安全操作直接关系到整个起重作业的安全性。以下从作业前、作业中、作业后的全流程&#xff0c;详细说明指挥人员需注意的安全事项&#xff1a; 一、作业前的安全准备 资质与状态检查&#xff…

【高等数学】傅里叶级数逼近例子

f ( x ) π 2 − ∣ x ∣ f(x)\frac{\pi}{2}-|x| f(x)2π​−∣x∣ 由于是偶函数只需要求 cos ⁡ ( n x ) , 1 \cos(nx),1 cos(nx),1 的系数 a n 0 a_n 0 an​0, n n n 是偶数 a n 1 ( 2 n − 1 ) 2 a_n \frac{1}{(2n-1)^2} an​(2n−1)21​, n n n 是奇数 则 f ( x )…

PowerBI企业运营分析—全动态盈亏平衡分析

PowerBI企业运营分析—全动态盈亏平衡分析 欢迎来到Powerbi小课堂&#xff0c;在竞争激烈的市场环境中&#xff0c;企业运营分析平台成为提升竞争力的核心工具。 该平台通过整合多源数据&#xff0c;实现关键指标的实时监控&#xff0c;从而迅速洞察业务动态&#xff0c;精准…

用ApiFox MCP一键生成接口文档,做接口测试

日常开发过程中&#xff0c;尤其是针对长期维护的老旧项目&#xff0c;许多开发者都会遇到一系列相同的困扰&#xff1a;由于项目早期缺乏严格的开发规范和接口管理策略&#xff0c;导致接口文档缺失&#xff0c;甚至连基本的接口说明都难以找到。此外&#xff0c;由于缺乏规范…

26考研 | 王道 | 计算机组成原理 | 三、存储系统

26考研 | 王道 | 计算机组成原理 | 三、存储系统 文章目录 26考研 | 王道 | 计算机组成原理 | 三、存储系统3.1 存储系统基本概念3.2 主存储器1. 主存储器的基本组成2. SRAM与DRAM1.DRAM和SRAM对比2.DRAM的刷新3.DRAM的地址线复用技术 3. 只读存储器ROM4.双端口RAM和多模块存储…

IDEA 开发PHP配置调试插件XDebug

1、安装PHP环境 为了方便&#xff0c;使用的PhpStudy。 安装路径&#xff1a;D:\resources\phpstudy_pro\Extensions\php\php7.3.4nts 2、下载Xdebug Xdebug: Downloads 选择对应的版本下载&#xff0c;本次使用的是7.3。 3、配置Xdebug 在php.ini中添加Xdebug配置。 D…

Go 语言的 GC 垃圾回收

序言 垃圾回收&#xff08;Garbage Collection&#xff0c;简称 GC&#xff09;机制 是一种自动内存管理技术&#xff0c;主要用于在程序运行时自动识别并释放不再使用的内存空间&#xff0c;防止内存泄漏和不必要的资源浪费。这篇文章让我们来看一下 Go 语言的垃圾回收机制是如…

60天python训练计划----day45

DAY 45 Tensorboard使用介绍 知识点回顾&#xff1a; tensorboard的发展历史和原理tensorboard的常见操作tensorboard在cifar上的实战&#xff1a;MLP和CNN模型 之前的内容中&#xff0c;我们在神经网络训练中&#xff0c;为了帮助自己理解&#xff0c;借用了很多的组件&#x…

RocketMQ基础概念的理解

1、生产者 生产者和主题之间存在多对多关系。一个生产者可以向多个主题发送消息&#xff0c;一个主题可以接收来自多个生产者的消息。这种多对多关系有助于提高性能扩展和灾难恢复能力。 2、消费者以及消费者组 一个队列可以被多个消费者&#xff08;其中这多个消费者必须分…

Flash烧录速度和加载配置速度(纯FPGA ZYNQ)

在工程综合完成或者implement完成后&#xff0c;打开综合设计或者实现设计。 toots--->Edit Device Properties--->打开比特流设置 将bitstream进行压缩 上图中&#xff0c;时钟频率选择的档位有限&#xff0c;最大为66MHZ io的bus width可以设置为x1,x2,x4 vivado在设计…

优化09-表连接

一、表连接介绍 表连接类型 表连接是关系型数据库关键特性&#xff0c;在关系型数据库中&#xff0c;表连接分为三类&#xff1a;循环嵌套连接&#xff08;Nested Loops Join&#xff09;、哈希连接&#xff08;Hash Join&#xff09;、合并排序连接&#xff08;Merge Sort J…

Dify工作流实践—根据word需求文档编写测试用例到Excel中

前言 这篇文章依赖到的操作可查阅我之前的文章&#xff1a; dify里的大模型是怎么添加进来的&#xff1a;在Windows本地部署Dify详细操作 flask 框架app.route()函数的开发和调用&#xff1a;PythonWeb开发框架—Flask工程创建和app.route使用详解 结构化提示词的编写&…

AWTK 嵌入式Linux平台实现多点触控缩放旋转以及触点丢点问题解决

前言 最近涉及海图的功能交互&#xff0c;多点触摸又开始找麻烦。 在PC/Web平台awtk是通过底层的sdl2库来实现多点触摸&#xff0c;但是在嵌入式Linux平台&#xff0c;可能是考虑到性能原因&#xff0c;awtk并没有采用sdl库来做事件处理&#xff0c;而是自己实现一个awtk-lin…