2020-11-11

如何去水印:
*(建议用谷歌浏览器),工具线上预览效
果: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
更惊喜的是接口返回的数据那叫一个详细,作者信息、音频地址、视频地址、平面图都有。但唯独没有无水印的视频 URL。只找到一个有水印的视频 URL,有点小失落,我又看了看这个地址,发现 wm 和我项目名有点像啊,不就是watermark 水印的缩写吗?

https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f030000bqk54kg2saj3lso3oh20&ratio=720p&line=0
好像又看到了一丝希望,我赶紧修改URL在浏览器中又试了一下,果然真的没水印了。

https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200f030000bqk54kg2saj3lso3oh20&ratio=720p&line=0
到这才发现抖音去水印 简单的让人感动,哈哈哈~

身体力行
既然原理都清晰了,剩下的就是一步一步实现功能了,原理看着挺简单的,但实现中还是遇到一点点小坑,浪费了不少时间。

实现过程只有简单的三步:

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) {
KaTeX parse error: Expected '}', got '#' at position 427: …tton"><a href="#̲##" rel="noopen…{rows[‘videoUrl’]}’,’ r o w s [ ′ d e s c ′ ] ′ ) " > < b u t t o n c l a s s = " l a y u i − b g − r e d l a y u i − b t n − s m l a y u i − b t n " > 下 载 视 频 < / b u t t o n > < / a > < / d i v > < d i v c l a s s = " p o p B u t t o n " > < t e x t a r e a i d = " v i d e o u r l " c o l s = " 1 " r o w s = " 1 " s t y l e = " h e i g h t : 0 ; w i d t h : 0 ; p o s i t i o n : a b s o l u t e ; " > {rows['desc']}')"><button class="layui-bg-red layui-btn-sm layui-btn">下载视频</button></a></div><div class="popButton"><textarea id="videourl" cols="1" rows="1" style="height:0;width:0;position: absolute;"> rows[desc])"><buttonclass="layuibgredlayuibtnsmlayuibtn"></button></a></div><divclass="popButton"><textareaid="videourl"cols="1"rows="1"style="height:0;width:0;position:absolute;">{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,页面中设置如下参数。

还简单做了下移动端适配,样式看着还可以,但是功能使用起来有点差强人意,后边在做优化了。

在这里插入图片描述
总结
很多东西就是这样,没认真研究之前总感觉深不可测,可一旦接触到技术的本质,又开始笑自己之前好蠢,懂与不懂有时就查那么一层窗户纸。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值