一、前言

大家好,俗话说的好,学习新的知识后要学以致用,在学习音视频的过程中,你有没有疑问,不知道音视频可以用来做什么。下面举几个例子,比较耳熟能详,被吹到风口的一些场景有: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 音视频小工具 - 下载抖音视频的更多相关文章

  1. python+fiddler 抓取抖音数据包并下载抖音视频

    这个我们要下载视频,那么肯定首先去找抖音视频的url地址,那么这个地址肯定在json格式的数据包中,所以我们就去专门查看json格式数据包 这个怎么找我就不用了,直接看结果吧 你找json包,可以选大 ...

  2. Python音视频开发:消除抖音短视频Logo的图形化工具实现

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 在<Python音视频开发:消除抖音短视频Logo和去电视台标的实现详解>节介绍了怎么通过Python+Moviepy+OpenCV实现 ...

  3. Python音视频开发:消除抖音短视频Logo和去电视台标

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 对于带Logo(如抖音Logo.电视台标)的视频,有三种方案进行Logo消除: 直接将对应区域用对应图像替换: 直接将对应区域模糊化: 通过变换将要 ...

  4. (数据科学学习手札80)用Python编写小工具下载OSM路网数据

    本文对应脚本已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 我们平时在数据可视化或空间数据分析的过程中经常会 ...

  5. 用 Python 下载抖音无水印视频

    说起抖音,大家或多或少应该都接触过,如果大家在上面下载过视频,一定知道我们下载的视频是带有水印的,那么我们有什么方式下载不带水印的视频呢?其实用 Python 就可以做到,下面我们来看一下. 很多人学 ...

  6. Python MoviePy中文教程导览及可执行音视频剪辑工具下载

    ☞ ░ 前往老猿Python博文目录 ░ <Python音视频剪辑库MoviePy1.0.3中文教程导览及可执行工具下载>是老猿两个关于moviepy的专栏<PyQt+moviepy ...

  7. Python音视频开发:消除抖音短视频Logo和去电视台标的实现详解

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 对于带Logo(如抖音Logo.电视台标)的视频,有三种方案进行Logo消除: 直接将对应区域用对应图像替换: 直接将对应区域模糊化: 通过变换将要 ...

  8. Python爬虫---爬取抖音短视频

    目录 前言 抖音爬虫制作 选定网页 分析网页 提取id构造网址 拼接数据包链接 获取视频地址 下载视频 全部代码 实现结果 待解决的问题 前言 最近一直想要写一个抖音爬虫来批量下载抖音的短视频,但是经 ...

  9. 今日头条、抖音、西瓜、火山、微视、陌陌等自媒体平台小视频批量下载工具v1.1.0(视频搬运福利)

    前言 目前各大自媒体平台爆火,网络流量暴涨,各大自媒体平台的小视频为广大个广告主带来了如泉涌般的的视频流量,更给广大的自媒体小编带来了丰厚的利益回报,想要创做更多的自媒体内容着实不易,下面给广大的小视 ...

  10. 用Google Brain的机器学习项目:Magenta,教神经网络学抖音小姐姐作曲。

    先上我们要学习的小姐姐 的美照.. 一.配置环境 1.自己配置环境:python,tensorflow,bazel(编译),java.然后下载magenta(https://github.com/te ...

随机推荐

  1. Python学习笔记之7.5 - 定义有默认参数的函数》》》直接在函数定义中给参数指定一个默认值,默认参数的值应该是不可变的对象

    问题: 你想定义一个函数或者方法,它的一个或多个参数是可选的并且有一个默认值. 解决方案: 定义一个有可选参数的函数是非常简单的,直接在函数定义中给参数指定一个默认值,并放到参数列表最后就行了.例如: ...

  2. noi 1.1 6 空格分隔输出

    描述 读入一个字符,一个整数,一个单精度浮点数,一个双精度浮点数,然后按顺序输出它们,并且要求在他们之间用一个空格分隔.输出浮点数时保留6位小数. 输入 共有四行:第一行是一个字符:第二行是一个整数: ...

  3. 在Unity3D中开发的Ghost Shader

    SwordMaster Ghost Shader 特点 此Shader是顶点片元Shader,由本人手动编写完成 此Shader已经在移动设备真机上进行过测试,可以直接应用到您的项目中 所支持的Uni ...

  4. SaaS、PaaS、IaaS的区别

    我们从SaaS.PaaS.IaaS的定义.工业应用以及具体案例几方面来介绍他们之间的区别 一.定义层面的区别 SaaS.PaaS.IaaS简单的说都属于云计算服务,也就是云计算+服务. 我们对于云计算 ...

  5. java Comparator和Comparable的区别?

    参考:https://blog.csdn.net/m0_71087031/article/details/124850080 Comparable是一个内比较器,可以和自己比较的 Comparator ...

  6. 解决CentOS 7.x虚拟机无法上网的问题

    参考地址:https://blog.csdn.net/weixin_43317914/article/details/124770393 1.关闭虚拟机 2.打开cmd,查看本机dns 3.打开虚拟机 ...

  7. 美国:KDB 986446 D01已生效

    1.美国FCC认证新要求 继2022年11月25日FCC发布了FCC 22-84法规禁止授权被认为对美国国家安全构成威胁的通信和视频监控设备后,2023年1月24日FCC又发布了KDB 986446 ...

  8. SaltStack学习笔记

    SaltStack三大功能: 1. 远程执行 2. 配置管理  (状态) 3.云管理 运维三板斧:监控.执行.配置 四种运行方式: 1.Local 2. Minion/Master   C/S架构 3 ...

  9. css穿透

    https://www.cnblogs.com/linjiangxian/p/13183412.html

  10. 安卓手机qpython使用感觉

    我是写C#的,最佳一时兴起,下载了个qpython来玩儿,发现这东西写点简单的爬虫还行,配合sqlite,可以做一些简单的事情,于是乎想写一个有趣的东西,在qpython写一个脚本,去收蚂蚁森林的能量 ...