1.前言大家好,俗话说,学了新知识,就要学以致用。在学习音视频的过程中,你有什么疑惑吗?音频和视频可以用来做什么。下面举几个例子,大家比较熟悉。一些被吹飞的场景包括:AI视觉计算、AI人脸识别。细化到一些小的领域,比如现在的直播技术,摄像头监控和流媒体;其他还有抖音里的美化和滤镜,背后是音视频领域的数字化妆技术。可见,音视频技术的应用已经应用到我们生活的方方面面。2.开发背景写这篇文章的目的是因为我有一个喜欢看抖音的朋友,经常有一些视频被作者设置为不可下载保存。如果朋友下次想再看,他就找不到了。.也有小伙伴想下载自己暗恋的妹纸作品。所以我告诉了我我的苦恼。作为朋友,我当然有义务帮助他走出困境。终于,两千年后,这玩意儿终于问世了。由于时间原因,来不及写前端页面了。以后有需要的同学可以关注或者私信我,我们一起学习。另外,写这篇文章的目的纯粹是为了学习。如果不小心被不法分子利用牟利,与我无关。请爱护学习环境,切记不要染指I。3.核心思想其实核心步骤就是两步1.根据复制自抖音的分享链接获取抖音的真实地址,需要借助网络编程技术解析到视频的真实地址。2.然后使用ffmpeg对网络视频流进行解码并保存到本地。四、主要技术点1、主要使用Java和一些网络调用的知识,如Restemplate的使用。Restemplate是springweb中的一个模板方法类。当然这里主要用到他的两个方法(headForHeaders、exchange)。可以使用其他工具类,也可以自己实现网络远程调用。2.JSON解析使用fastjson,版本号可选,一般兼容。3、StringUtils是commons.lang3包下的工具类,不要导入错包。4、ffmpeg流媒体使用的第三方依赖是javacv,1.4.3版本。需要具体的引用依赖,关注或私信我。5.如果你对ffmpeg的基本概念不是很清楚,音视频的基本概念,比如视频帧,音频帧,码率等,这里我只说技术的应用,不做介绍详细介绍这些原则。搜索的很多,有兴趣的可以自己查下面的。6.使用javacv中的FFmpegFrameGrabber帧抓取器获取音频/视频帧。有了这个抓取器,你就可以省去打开视频流、寻找解码器、判断音频帧和视频帧等一堆复杂的调用原生API的操作。网上的一个介绍/总结FFmpegFrameGrabber是用来捕捉/抓取视频图像和音频样本的。封装了获取流信息、自动猜测视频解码格式、音视频解码、将解码后的像素数据(像素格式可配置)或音频数据保存在Frame中并返回等具体API。7.也可以使用ffmpeg命令行下载。命令如下:ffmpeg-ihttps://xxx.mp4-ccopy-fflvAibei.flv但是这种方式需要部署机安装ffmpeg,所以暂时不考虑这种方式。8、利用javacv中的FrameRecorder将解码后的图像像素点编码成相应的代码和格式推送出去。将它们保存在本地意味着将它们推送到本地文件。下面是音视频大佬eguid对FrameRecorder的介绍,总结一下FrameRecorder用于音视频/图片的封装、编码、推流、录制、保存等操作。取出从FrameGrabber或FrameFilter获取的Frame中的数据,进行编码、封装、流化、发送等操作。为了便于理解和阅读,下面一开始我们将FrameRecorder统称为:recorder。五、详细思路1.链接分析&接口分析(1)、Java正则表达式从字符串中提取url。(2)使用RestTemplate.headForHeaders()方法获取资源URI的请求头信息,只关注获取HTTP请求头信息。(3)第一步提取的url在浏览器模拟中可以找到,会被重定向到一个新的地址,重定向的地址是从请求头中获取的,即从请求头中获取location,以及然后从location获取视频的真实id。(4)根据视频的真实id和抖音的接口获取视频信息,比如播放信息、作者信息、背景音乐信息等,使用json逐层解析得到url播放地址。2.ffmpeg拉取并保存流(1)。使用ffmpeg获取url视频帧的第一帧,检查视频是否为空视频。(2)创建视频流录像机,设置录像参数、分辨率、格式、输出位置。(3)循环获取视频帧,使用录像机逐帧录制视频。六、核心代码1、使用正则表达式提取url/***正则表达式提取url*@paramtext*@return*/publicstaticStringpickURI(Stringtext){//eg:text="5.1GV:/一出场就给人一种江南的感觉%刘亦菲%亮点%宋红马https://v.douyin.com/e614JkV/肚皮系统二连,打开抖音搜索,直接看kan视频!模式pattern=Pattern.compile("https?://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]");匹配器匹配器=pattern.matcher(text);如果(matcher.find()){returnmatcher.group();}返回””;}2。发起网络调用,解析json获取真实地址publicfinalstaticStringDOU_YIN_WEB_API="https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=";/***根据分配的分享码下载抖音视频*@paramtext*@throwsFrameGrabber.Exception*@throwsFrameRecorder.Exception*/publicstaticStringdouYin(Stringtext)throwsFrameGrabber.Exception,FrameRecorder.Exception{//字符串url=pickURI(text);RestTemplate客户端=newRestT嵌入();//HttpHeadersheaders=client.headForHeaders(url);字符串位置=headers.getLocation().toString();Stringvid=StringUtils.substringBetween(location,"/video/","/?");RestTemplaterestTemplate=newRestTemplate();HttpHeadersqueryHeaders=newHttpHeaders();queryHeaders.set(HttpHeaders.USER_AGENT,"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/89.0.4389.114Safari/537.36");HttpEntity>(){});如果(list.size()==0){返回“”;}JSONObjectitem=list.get(0);JSONObject视频=item.getJSONObject("视频");JSONObjectplayAddr=video.getJSONObject("play_addr");JSONArrayurlList=playAddr.getJSONArray("url_list");List
>(){});如果(urlListArr.size()==0){返回“”;}返回urlListArr.get(0);//VideoConvert.record(finalAddr,"/home/yinyue/upload/红马.flv");}3、ffmpeg拉流并保存/***转存视频*@paraminput*@paramoutFile*@throwsFrameGrabber.Exception*@throwsFrameRecorder.Exception*/publicstaticvoidrecord(Stringinput,StringoutFile)throwsFrameGrabber.Exception,FrameRecorder.Exception{FrameGrabber抓取器=newFFmpegFrameGrabber(输入);抓取器.start();OpenCVFrameConverter.ToIplImage转换器=newOpenCVFrameConverter.ToIplImage();框架frame=grabber.grab();opencv_core.IplImageimage=null;if(frame==null){System.out.println("第一帧为空,请检查视频源");返回;}image=converter.convert(frame);FrameRecorder记录器=FrameRecorder.createDefault(outFile,frame.imageWidth,frame.imageHeight);recorder.setVideoCodec(AV_CODEC_ID_H264);recorder.setFormat("flv");录音机.setFrameRate(25);记录器.setGopSize(25);记录器.start();帧保存帧;while((frame=grabber.grab())!=null){saveFrame=converter.convert(image);//获取类型,视频或音频//EnumSet
