乐趣区

关于音视频: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();}

七、运行截图

运行实现后本地胜利生成了下载的视频文件

八、作者心得

咱们生在一个技术百花齐放,突飞猛进的年代,生于这个时代即是侥幸也是悲痛,在如此浩瀚无穷无尽的常识更迭浪潮中,很难保障全能,尽如人意;有的人专一于算法,有的人专一与数据处理,还有的人入手能力不行,然而实践能力极强,比方驰名物理学家杨振宁,有的人专一于如何利用落地,致力于将技术利用于社会生存,所以,如果本文对你有用,请不吝赞叹,如果你感觉内容过于肤浅或者是令你感到不适,也请沉默不言,相互留一份体面。

退出移动版