Javacv 音视频小工具 - 下载抖音视频
一、前言
大家好,俗话说的好,学习新的知识后要学以致用,在学习音视频的过程中,你有没有疑问,不知道音视频可以用来做什么。下面举几个例子,比较耳熟能详,被吹到风口的一些场景有:AI 视觉计算, AI 人脸识别. 细化到一些小的领域,如现在直播技术,摄像头监控拉流;其他还有抖音中的美颜,滤镜,其背后是使用的音视频领域的数字化妆技术。由此可见,音视频技术应用已经应用于我们生活的方方面面。
二、开发背景
想写这篇文章的目的是因为,我有个朋友平时喜欢刷抖音,就经常有一些视频被作者设置成了不可下载保存,朋友下次想再看的话就找不到了。 还有朋友想下载暗恋的妹纸的作品。所以就把苦闷告诉我了,作为朋友当然有义务帮助他走出困境啦,终于,Two thousand years later 的今天,这个小工具终于问世,因为时间原因,来不及写前端页面了,后面有需要的同学可以关注或者私信我,我们一起学习,另外,写本文的目的纯粹是以学习为主,如不小心被不法分子滥用以盈利为目的,与本人无关,请广大道友积极爱护学习环境,记得不要连累我。
三、核心思想
其实核心步骤就两步
1、根据抖音上复制的分享链接获取到抖音的真实地址,需要使用网络编程技术解析到视频的真实地址。
2、然后使用 ffmpeg 解码网络视频流,保存到本地。
四、主要技术点
1、主要使用 Java 与 一些网络调用的知识,例如 Restemplate 的使用,Restemplate 是 spring web 中的一个模板方法类,这里主要用到了他的两个方法(headForHeaders, exchange),当然也可以用其他的工具类或者自己去实现网络远程调用。
2、JSON 解析使用 fastjson,版本号随意,一般都可以兼容。
3、StringUtils 是使用 commons.lang3 包下面中的工具类,不要导错包啦。
4、ffmpeg 拉流使用的第三方依赖是 javacv,版本 1.4.3 版本。如需具体引用依赖,关注或者私信我。
5、如果你对于 ffmpeg 基本概念,音视频基本概念,如视频帧, 音频帧,码率等基本知识不是非常清楚,这里我只说技术的应用,关于原理的讲解,不做过多赘述,网上一搜一大堆,有兴趣可以自己去了解以下。
6、使用 javacv 中的 FFmpegFrameGrabber 帧抓取器来获取音/视频帧,用这个抓取器,可以省略原生的 API 调用的一堆复杂操作,例如打开视频流,查找解码器,判断音频帧和视频帧。
来自网上的一段介绍/概括
FFmpegFrameGrabber 用于采集/抓取视频图像和音频采样。封装了检索流信息,自动猜测视频解码格式,音视频解码等具体 API,并把解码完的像素数据(可配置像素格式)或音频数据保存到 Frame 中返回等功能。
7、还可以使用 ffmpeg 命令行的方式进行下载。命令如下:
ffmpeg -i https://xxx.mp4 -c copy -f flv 艾北.flv
但是这种方式需要部署机安装 ffmpeg,所以暂时不考虑这种方式了。
8、使用 javacv 中的 FrameRecorder 录制器来把已经解码的图像像素编码成对应的编码和格式推流出去,这里保存到本地就是推流到本地文件。
以下是音视频大佬 eguid 对于 FrameRecorder 的介绍概括
FrameRecorder 用于音视频/图片的封装、编码、推流和录制保存等操作。把从 FrameGrabber 或者 FrameFilter 获取的 Frame 中的数据取出并进行编码、封装、推流发送等操作流程。为了方便理解和阅读,下文开始我们统一把 FrameRecorder 简称为:录制器。
五、详细思路
1、链接解析 &接口解析
(1)、Java 正则表达式从字符串中提取出 url。
(2)、使用 RestTemplate.headForHeaders() 方法获取某个资源的 URI 的请求头信息,并且只专注于获取 HTTP 请求头信息。
(3)、第一步中提取出的 url 在浏览器中模拟可以发现, 会重定向到一个新的地址,从请求头中获取重定向后的地址, 即从 header 中获取 location,然后从 location 中获取视频的真实 id。
(4)、根据视频真实 id 和抖音的接口去获取视频信息,如播放信息,作者信息,背景音乐信息等等,使用 json 一层一层解析出来播放地址的 url。
2、ffmpeg 拉流并保存
(1)、使用 ffmpeg 获取 url 视频帧的第一帧,检测视频是否是空视频。
(2)、创建视频流录制器,设置视频参数,分辨率,格式,输出位置。
(3)、循环获取视频帧,使用录制器 recorder 逐帧录制视频帧。
六、核心代码
1、使用正则提取 url
/**
* 正则表达式提取 url
* @param text
* @return
*/
public static String pickURI(String text) {
// eg: text = "5.1 GV:/ 一出场就给人一种江南的感觉%刘亦菲 %精彩片段 %歌曲红马 https://v.douyin.com/e614JkV/ 腹制佌lian接,打开Dou音搜索,直接观kan视頻!";
Pattern pattern = Pattern.compile("https?://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]");
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
return matcher.group();
}
return "";
}
2、发起网络调用,解析 json 获取真实地址
public final static String DOU_YIN_WEB_API = "https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids="; /**
* 根据赋值的分享码下载抖音视频
* @param text
* @throws FrameGrabber.Exception
* @throws FrameRecorder.Exception
*/
public static String douYin(String text) throws FrameGrabber.Exception, FrameRecorder.Exception {
//
String url = pickURI(text);
RestTemplate client = new RestTemplate();
//
HttpHeaders headers = client.headForHeaders(url);
String location = headers.getLocation().toString();
String vid = StringUtils.substringBetween(location, "/video/", "/?"); RestTemplate restTemplate = new RestTemplate();
HttpHeaders queryHeaders = new HttpHeaders();
queryHeaders.set(HttpHeaders.USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36");
HttpEntity<String> entity = new HttpEntity<>(queryHeaders);
ResponseEntity<JSONObject> response = restTemplate.exchange(DOU_YIN_WEB_API + vid, HttpMethod.GET, entity, JSONObject.class); if(response.getStatusCodeValue() != 200) {
return "";
}
JSONObject body = response.getBody();
assert body != null;
List<JSONObject> list = JSONArray.parseObject(body.getJSONArray("item_list").toJSONString(), new TypeReference<List<JSONObject>>(){});
if(list.size() == 0) {
return "";
}
JSONObject item = list.get(0);
JSONObject video = item.getJSONObject("video");
JSONObject playAddr = video.getJSONObject("play_addr");
JSONArray urlList = playAddr.getJSONArray("url_list");
List<String> urlListArr = JSONArray.parseObject(urlList.toJSONString(), new TypeReference<List<String>>(){});
if(urlListArr.size() == 0) {
return "";
}
return urlListArr.get(0);
// VideoConvert.record(finalAddr, "/home/yinyue/upload/红马.flv");
}
3、ffmpeg 拉流并保存
/**
* 转存视频流
* @param input
* @param outFile
* @throws FrameGrabber.Exception
* @throws FrameRecorder.Exception
*/
public static void record(String input, String outFile) throws FrameGrabber.Exception, FrameRecorder.Exception {
FrameGrabber grabber = new FFmpegFrameGrabber(input);
grabber.start();
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
Frame frame = grabber.grab();
opencv_core.IplImage image = null;
if(frame == null) {
System.out.println("第一帧为空,请检查视频源");
return;
}
image = converter.convert(frame);
FrameRecorder recorder = FrameRecorder.createDefault(outFile, frame.imageWidth, frame.imageHeight);
recorder.setVideoCodec(AV_CODEC_ID_H264);
recorder.setFormat("flv");
recorder.setFrameRate(25);
recorder.setGopSize(25);
recorder.start();
Frame saveFrame;
while((frame = grabber.grab()) != null) {
saveFrame = converter.convert(image);
// 获取类型, 视频或者音频
// EnumSet<Frame.Type> videoOrAudio = saveFrame.getTypes();
// 录制视频
recorder.record(saveFrame);
}
recorder.close();
}
七、运行截图
运行完成后本地成功生成了下载的视频文件
八、作者心得
我们生在一个技术百花齐放,日新月异的年代,生于这个时代即是幸运也是悲哀,在如此浩瀚无穷无尽的知识更迭浪潮中,很难保证全能,尽善尽美;有的人专注于算法,有的人专注与数据处理,还有的人动手能力不行,但是理论能力极强,比如著名物理学家杨振宁,有的人专注于如何应用落地,致力于将技术应用于社会生活,所以,如果本文对你有用,请不吝赞赏,如果你感觉内容过于浅薄或者是令你感到不适,也请缄默不言,互相留一份体面。
Javacv 音视频小工具 - 下载抖音视频的更多相关文章
- python+fiddler 抓取抖音数据包并下载抖音视频
这个我们要下载视频,那么肯定首先去找抖音视频的url地址,那么这个地址肯定在json格式的数据包中,所以我们就去专门查看json格式数据包 这个怎么找我就不用了,直接看结果吧 你找json包,可以选大 ...
- Python音视频开发:消除抖音短视频Logo的图形化工具实现
☞ ░ 前往老猿Python博文目录 ░ 一.引言 在<Python音视频开发:消除抖音短视频Logo和去电视台标的实现详解>节介绍了怎么通过Python+Moviepy+OpenCV实现 ...
- Python音视频开发:消除抖音短视频Logo和去电视台标
☞ ░ 前往老猿Python博文目录 ░ 一.引言 对于带Logo(如抖音Logo.电视台标)的视频,有三种方案进行Logo消除: 直接将对应区域用对应图像替换: 直接将对应区域模糊化: 通过变换将要 ...
- (数据科学学习手札80)用Python编写小工具下载OSM路网数据
本文对应脚本已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 我们平时在数据可视化或空间数据分析的过程中经常会 ...
- 用 Python 下载抖音无水印视频
说起抖音,大家或多或少应该都接触过,如果大家在上面下载过视频,一定知道我们下载的视频是带有水印的,那么我们有什么方式下载不带水印的视频呢?其实用 Python 就可以做到,下面我们来看一下. 很多人学 ...
- Python MoviePy中文教程导览及可执行音视频剪辑工具下载
☞ ░ 前往老猿Python博文目录 ░ <Python音视频剪辑库MoviePy1.0.3中文教程导览及可执行工具下载>是老猿两个关于moviepy的专栏<PyQt+moviepy ...
- Python音视频开发:消除抖音短视频Logo和去电视台标的实现详解
☞ ░ 前往老猿Python博文目录 ░ 一.引言 对于带Logo(如抖音Logo.电视台标)的视频,有三种方案进行Logo消除: 直接将对应区域用对应图像替换: 直接将对应区域模糊化: 通过变换将要 ...
- Python爬虫---爬取抖音短视频
目录 前言 抖音爬虫制作 选定网页 分析网页 提取id构造网址 拼接数据包链接 获取视频地址 下载视频 全部代码 实现结果 待解决的问题 前言 最近一直想要写一个抖音爬虫来批量下载抖音的短视频,但是经 ...
- 今日头条、抖音、西瓜、火山、微视、陌陌等自媒体平台小视频批量下载工具v1.1.0(视频搬运福利)
前言 目前各大自媒体平台爆火,网络流量暴涨,各大自媒体平台的小视频为广大个广告主带来了如泉涌般的的视频流量,更给广大的自媒体小编带来了丰厚的利益回报,想要创做更多的自媒体内容着实不易,下面给广大的小视 ...
- 用Google Brain的机器学习项目:Magenta,教神经网络学抖音小姐姐作曲。
先上我们要学习的小姐姐 的美照.. 一.配置环境 1.自己配置环境:python,tensorflow,bazel(编译),java.然后下载magenta(https://github.com/te ...
随机推荐
- 阿里云 rocketMq 延时消息
初始化消费者和生产者 生产者 设置rocketmq的accesskey 和secretkey 以及rocketmq的 binder server. 首先 编辑一个配置类,将关于配置rocketmq的东 ...
- win常用的dos命令
常用的dos命令 开启dos终端的两种方式: win+r后输入cmd指令 在资源管理器上方的路径窗口直接输入cmd,即可开启指定路径下的cmd终端,省去了cd/d这一步 注:在dos终端里ctrl+v ...
- 解决vuex“状态管理调用报错”报错为:"Uncaught ReferenceError: mapactions is not defined"
报错: 源码: <script> import Vuex from 'vuex'; import {mapActions,mapGetters} from 'vuex'; // conso ...
- python修改图片名
1 import glob 2 import os 3 4 inputPath = r'E:/data/pic/cat' 5 fileList = glob.glob(inputPath + '/*' ...
- WSL2与ensp的40故障
在使用ensp做radius认证的时候看到了Linux平台的freeradius认证服务器,于是使用了Windows平台的sub system: WSL2,按照网上的教程安装,并且安装了docker ...
- backward函数中gradient参数的一些理解
当标量对向量求导时不需要该参数,但当向量对向量求导时,若不加上该参数则会报错,显示"grad can be implicitly created only for scalar output ...
- 10 soundJs 初体验
最近想做一个h5的小游戏所以用上了soundjs. 还在开发中 http://www.hetenglife.com/mouse/game.html 刚刚把控制做完. 首先是要导入这个文件 <s ...
- vins-fusion(1)安装编译
https://github.com/HKUST-Aerial-Robotics/VINS-Fusion https://blog.csdn.net/haner27/article/details/1 ...
- python-官网下载安装教程
1.官网地址:https://www.python.org/ 2.点击Downloads,选择Windows版本 3.找到对应版本,这里以3.9.12为例,选择结尾为executable instal ...
- SQL初级知识点
一,表 表中的列叫做字段,行叫记录也叫元组. 主键:唯一的标识表中的某一条记录 外键:一个表的主键作为另一个表的外键,表示两个表之间的关系.一般将外键写在记录的一方,比如部门号和员工号,应该将部门号作 ...