手写一个抖音视频去水印Java工具,千万别刚一个程序员 |
您所在的位置:网站首页 › 我下载一个抖音抖音 › 手写一个抖音视频去水印Java工具,千万别刚一个程序员 |
说一下我为什么要做个抖音视频去水印工具,其实是因为我的沙雕女友,她居然刚我~ 有天晚上她在抖音看见一个非常具有 教育意义 的视频,“男人疼媳妇就该承包全部家务活”,然后它就想把视频下载下来,分享到她的姐妹群交流 驭夫 心得。 可是大家都知道抖音下载的视频是带水印,作为一个重度强迫症选手这是不被允许的,没办法那就找找有没有去水印工具吧,找了一圈要不就是收费,要么下载不下来,主上脸上的笑容也在逐渐消失。 我在边上调侃了一句:也没多难,要不我给你做一个!“你行吗?” 然后投来了一个不屑的眼神。 哎呀!本来就开个玩笑,居然说我不行,这就不能忍了,我得证明给你看看!男人嘛,就受不了这话 “(建议用谷歌浏览器),工具线上预览效果:http://47.93.6.5:8888/index ”下边和大家一起分析下做这个去水印工具的思路,很多人乍一听 去水印 ,下意识的觉得是一种什么牛比的算法,其实这是一种假象~ 刨根问底虽说要争口气,可刚开始做的时候我也真是一脸懵逼,因为根本不知道该从哪入手,去水印什么原理啊?难不成我还要写个算法? 找了一个抖音视频的分享链接,一点点分析,不难发现这是个经过处理的短链接,那这个短链接一定会重定向到真实的视频地址 URL 。 https://v.douyin.com/JSkuhE4/浏览器中输入短链接得到了下边这个 URL ,以我的经验判断URL中的 6820792802394262795 很有可能是视频的唯一ID,而唯一ID通常用来作为获取详情接口的入参,哎嘿~ 好像有点头绪了。 https://www.iesdouyin.com/share/video/6820792802394262795/赶紧祭出 F12 大法打开控制台,在众多请求中发现这么一个接口,它居然用到了上边的唯一ID。 https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=6820792802394262795
既然原理都清晰了,剩下的就是一步一步实现功能了,原理看着挺简单的,但实现中还是遇到一点点小坑,浪费了不少时间。 实现过程只有简单的三步: 1、从输入框中过滤取出视频短连接 2、短连接传到后端解析出无水印的视频 URL 3、视频 URL传递给前端预览、下载 后端并没有什么难度,一步一步按照上边分析的流程解析真实视频 URL 就可以了。 “注意 :我们想得到的地址URL,都是当前短连接URL 经过重定向后的URL。而抖音有些链接是不支持浏览器访问的,所以要手动修改 User-agent 属性模拟移动端访问才可以。 ” /** * @param url * @author xiaofu * @description 获取当前链接重定向后的url * @date 2020/9/15 12:43 */ public static String getLocation(String url) { try { URL serverUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection) serverUrl.openConnection(); conn.setRequestMethod("GET"); conn.setInstanceFollowRedirects(false); conn.setRequestProperty("User-agent", "ua");//模拟手机连接 conn.connect(); String location = conn.getHeaderField("Location"); return location; } catch (Exception e) { e.printStackTrace(); } return ""; }下边是完整的后端实现,可以看到代码量非常的少。 /** * @author xiaofu-公众号:程序员内点事 * @description 抖音无水印视频下载 * @date 2020/9/15 18:44 */ @Slf4j @Controller public class DYController { public static String DOU_YIN_BASE_URL = "https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids="; /** * @param url * @author xiaofu * @description 解析抖音无水印视频 * @date 2020/9/15 12:43 */ @RequestMapping("/parseVideoUrl") @ResponseBody public String parseVideoUrl(@RequestBody String url) throws Exception { DYDto dyDto = new DYDto(); try { url = URLDecoder.decode(url).replace("url=", ""); /** * 1、短连接重定向后的 URL */ String redirectUrl = CommonUtils.getLocation(url); /** * 2、拿到视频对应的 ItemId */ String videoUrl = ""; String musicUrl = ""; String videoPic = ""; String desc = ""; if (!StringUtils.isEmpty(redirectUrl)) { /** * 3、用 ItemId 拿视频的详细信息,包括无水印视频url */ String itemId = CommonUtils.matchNo(redirectUrl); StringBuilder sb = new StringBuilder(); sb.append(DOU_YIN_BASE_URL).append(itemId); String videoResult = CommonUtils.httpGet(sb.toString()); DYResult dyResult = JSON.parseObject(videoResult, DYResult.class); /** * 4、无水印视频 url */ videoUrl = dyResult.getItem_list().get(0) .getVideo().getPlay_addr().getUrl_list().get(0) .replace("playwm", "play"); String videoRedirectUrl = CommonUtils.getLocation(videoUrl); dyDto.setVideoUrl(videoRedirectUrl); /** * 5、音频 url */ musicUrl = dyResult.getItem_list().get(0).getMusic().getPlay_url().getUri(); dyDto.setMusicUrl(musicUrl); /** * 6、封面 */ videoPic = dyResult.getItem_list().get(0).getVideo().getDynamic_cover().getUrl_list().get(0); dyDto.setVideoPic(videoPic); /** * 7、视频文案 */ desc = dyResult.getItem_list().get(0).getDesc(); dyDto.setDesc(desc); } } catch (Exception e) { log.error("去水印异常 {}", e); } return JSON.toJSONString(dyDto); } }前端实现也比较简单,拿到后端解析出来的视频URL 预览播放、下载就OK了。 为快速实现我用了老古董JQuery,我这个年纪的人对它感情还是很深厚的,UI 框架用的 layer.js。源码后边会分享给大家,就不全贴出来了。 $.ajax({ url: '/parseVideoUrl', type: 'POST', data: {"url": link}, success: function (data) { $('.qsy-submit').attr('disabled', false); try { var rows = JSON.parse(data); layer.close(index); layer.open({ type: 1, title: false, closeBtn: 1, shadeClose: true, skin: 'yourclass', content: `下载视频${rows['videoUrl']}复制链接下载音频 ` //content: ` ` }); } catch (error) { layer.alert('错误信息:' + error, { title: '异常', skin: 'layui-layer-lan', closeBtn: 0, anim: 4 //动画类型 }); return false; } }, error: function (err) { console.log(err); layer.close(index); $('.qsy-submit').attr('disabled', false); }, done: function () { layer.close(index); } }) }) “注意:我们在自己的网站中引用其它网站的资源URL,由于不在同一个域名下referrer 不同,通常会遇到三方网站的防盗链拦截,所以要想正常访问三方资源,必须要隐藏请求的referrer,页面中设置如下参数。 ”还简单做了下移动端适配,样式看着还可以,但是功能使用起来有点差强人意,后边在做优化了。 很多东西就是这样,没认真研究之前总感觉深不可测,可一旦接触到技术的本质,又开始笑自己之前好蠢,懂与不懂有时就查那么一层窗户纸。 本文源码: https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-douyin-watermark 有热门推荐???? 卧槽!我随便写的一个 API 竟获得 2.5 亿的访问量... 面试官:来说说单点登录的三种实现方式 来我们公司面试必问的41道 SpringBoot 面试题,不看亏大了! 2020年10月程序员工资统计,平均14459元 高手都这么给 Spring MVC 做单元测试! 公司接口裸奔10年了,也没啥事。有必要用开放API接口签名验证? 干货分享:扫码关注下面的公众号获取面试资料+项目实战资料(电商/聚合支付) 点击阅读原文,获免费JVM+MySQL+设计模式+分布式+微服务完整面试资料 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |