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

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.xdnf.cn/news/10689.html

相关文章:

  • 从零开始,搭建一个基于 Django 的 Web 项目
  • django入门-orm数据库操作
  • unity UI Canvas“高”性能写法
  • 如何轻松地将数据从 iPhone传输到iPhone 16
  • 【JSON-to-Video】设置背景视频片断
  • 【OCCT+ImGUI系列】011-Poly-Poly_Triangle三角形面片
  • GIC v3 v4 虚拟化架构
  • 业态即战场:零售平台的生意模型与系统设计解构
  • Elasticsearch集群最大分片数设置详解:从问题到解决方案
  • [特殊字符] Unity UI 性能优化终极指南 — ScrollRect篇
  • spring-boot-admin实现对微服务监控
  • 提升四级阅读速度方法
  • python学习(一)
  • git checkout C1解释
  • Windows 下彻底删除 VsCode
  • 开疆智能Profinet转Profibus网关连接CMDF5-8ADe分布式IO配置案例
  • RequestRateLimiterGatewayFilterFactory
  • 亚马逊Woot提报常见问题第一弹
  • es 的字段类型(text和keyword)
  • PostgreSQL的扩展 passwordcheck
  • 深入剖析物联网边缘计算技术:架构、应用与挑战
  • 学习threejs,交互式神经网络可视化
  • 基于Java的OPCDA采集中间件
  • Vue.js教学第十八章:Vue 与后端交互(二):Axios 拦截器与高级应用
  • Windows 下部署 SUNA 项目:虚拟环境尝试与最终方案
  • 下载并运行自制RAG框架
  • C# winform教程(二)----button
  • Python文件操作与JSON处理完全指南
  • Python训练第四十三天
  • 从计量到通信,DJSF1352-D为快充桩系统提供了怎样的解决方案?