>  기사  >  Java  >  Java 프로그래머가 Douyin 비디오 워터마크 제거 도구를 직접 작성했습니다.

Java 프로그래머가 Douyin 비디오 워터마크 제거 도구를 직접 작성했습니다.

coldplay.xixi
coldplay.xixi앞으로
2020-11-27 17:02:3012215검색

java basics 칼럼에서는 워터마크 도구 제거 방법을 소개합니다.

Java 프로그래머가 Douyin 비디오 워터마크 제거 도구를 직접 작성했습니다.

관련 학습 권장 사항: java 기본

모든 원인에는 결과가 있어야 합니다.

제가 Douyin 비디오 워터마크 제거 도구를 만들고 싶은 이유를 말씀드리겠습니다. 사실은 제 때문입니다. 모래 조각상 여자친구가 실제로 저를 때렸어요~

어느 날 밤 그녀는 Douyin에서 "아내를 사랑하는 남자는 집안일을 다 해야 한다"는 매우 교육적인 비디오를 보고 다운로드하고 싶어했습니다. 남편 통제에 대한 경험을 교환하기 위해 자매 그룹과 공유한 동영상입니다. 教育意义 的视频,“男人疼媳妇就该承包全部家务活”,然后它就想把视频下载下来,分享到她的姐妹群交流 驭夫 心得。

可是大家都知道抖音下载的视频是带水印,作为一个重度强迫症选手这是不被允许的,没办法那就找找有没有去水印工具吧,找了一圈要不就是收费,要么下载不下来,主上脸上的笑容也在逐渐消失。

我在边上调侃了一句:也没多难,要不我给你做一个!“你行吗?” 然后投来了一个不屑的眼神。

Java 프로그래머가 Douyin 비디오 워터마크 제거 도구를 직접 작성했습니다.

哎呀!本来就开个玩笑,居然说我不行,这就不能忍了,我得证明给你看看!男人嘛,就受不了这话

先看下我做的去水印工具线上预览效果: 47.93.6.5:8888/index

Java 프로그래머가 Douyin 비디오 워터마크 제거 도구를 직접 작성했습니다.

下边和大家一起分析下做这个去水印工具的思路,很多人乍一听 去水印 ,下意识的觉得是一种什么牛比的算法,其实这是一种假象~

刨根问底

虽说要争口气,可刚开始做的时候我也真是一脸懵逼,因为根本不知道该从哪入手,去水印什么原理啊?难不成我还要写个算法?

找了一个抖音视频的分享链接,一点点分析,不难发现这是个经过处理的短链接,那这个短链接一定会重定向到真实的视频地址 URL

https://v.douyin.com/JSkuhE4/

浏览器中输入短链接得到了下边这个 URL ,以我的经验判断URL中的 6820792802394262795 很有可能是视频的唯一ID,而唯一ID通常用来作为获取详情接口的入参,哎嘿~ 好像有点头绪了。

https://www.iesdouyin.com/share/video/6820792802394262795/

Java 프로그래머가 Douyin 비디오 워터마크 제거 도구를 직접 작성했습니다.

赶紧祭出 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

Java 프로그래머가 Douyin 비디오 워터마크 제거 도구를 직접 작성했습니다.
到这才发现抖音去水印 简单的让人感动,哈哈哈~

身体力行

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

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

  • 1、从输入框中过滤取出视频短连接
  • 2、短连接传到后端解析出无水印的视频 URL
  • 3、视频 URL传递给前端预览、下载

后端并没有什么难度,一步一步按照上边分析的流程解析真实视频 URL

하지만 Douyin에서 다운로드한 동영상에는 워터마크가 있다는 것은 누구나 알고 있습니다. 심각한 강박 장애가 있는 플레이어로서 이것이 불가능하다면, 워터마크 제거 도구를 찾아보세요. .다운로드도 안 되고, 주인님 얼굴의 미소도 점점 사라지고 있어요. 🎜🎜옆에서 농담을 했어요. 별로 어렵지 않은데, 제가 하나 만들어 드리는 건 어때요? "괜찮아?" 그러자 그는 경멸적인 표정을 지었다. 🎜🎜여기에 이미지 설명을 삽입하세요🎜🎜죄송합니다! 농담이었는데 실제로는 내가 좋지 않다고 말씀하셨네요. 이건 참을 수 없어요. 증명해야 해요! 남자들 참을 수가 없어 🎜
🎜 먼저 제가 만든 워터마크 제거 도구의 온라인 미리보기 효과를 보세요: 47.93.6.5:8888/index🎜
🎜워터마크 제거 미리보기🎜🎜 이 워터마크 제거를 ​​​​만드는 아이디어를 분석해 보겠습니다. 많은 분들이 워터마크 제거를 들었을 때 무의식적으로 무슨 멋진 알고리즘인 줄 알았습니다. 사실은 환상이었습니다~🎜🎜🎜🎜더 달라고 하더군요. information🎜🎜논쟁을 해야 하겠지만 처음 시작할 때 워터마크 제거의 원리가 무엇인지 몰라서 정말 혼란스럽습니다. 여전히 알고리즘을 작성해야 하는 것이 가능합니까? 🎜🎜Douyin 동영상에 대한 공유 링크를 찾았습니다. 약간의 분석 끝에 이것이 처리된 짧은 링크라는 것을 어렵지 않게 찾을 수 있었습니다. 그러면 이 짧은 링크는 확실히 실제 동영상 주소 URL로 리디렉션됩니다. >. 🎜
/**
* @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 "";
    }
🎜 브라우저에 짧은 링크를 입력하고 아래 URL을 가져옵니다. 내 경험에 따르면 URL6820792802394262795가 가장 많은 것으로 판단됩니다. 동영상일 가능성이 높습니다. 고유 ID는 일반적으로 세부정보를 얻기 위한 인터페이스의 입력 매개변수로 사용됩니다. 헤헤~ 몇 가지 단서가 있는 것 같습니다. 🎜
/**
 * @author xiaofu-公众号:程序员内点事
 * @description 抖音无水印视频下载
 * @date 2020/9/15 18:44
 */@Slf4j
@Controllerpublic 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);
    }}
🎜워터마크가 있는 링크🎜🎜서둘러 F12 Dafa는 콘솔을 열고 많은 요청 중에서 이러한 인터페이스를 발견했습니다. 실제로는 위의 고유 ID를 사용했습니다. 🎜
$.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: `<p></p><p></p><p><a><button>下载视频</button></a></p><p><textarea>${rows['videoUrl']}</textarea><button>复制链接</button></p><p><a><button>下载音频</button></a></p><video><source> </source></video>`
                //content: `<video><source> </source></video>`
            });

        } 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은 없습니다.

워터마크가 있는 항목만 발견됨 동영상 URL이 조금 실망스러웠습니다. 주소를 다시 살펴보니 wm이 제 프로젝트 이름과 조금 비슷하더군요. 그냥 워터마크였습니다. .워터마크의 약어? 🎜
 <!-- 解决访问视频url 请求403异常 -->
 <meta>
🎜
있는 것 같아요 다시 한 번 희망을 품고 빠르게 URL을 수정하고 브라우저에서 다시 시도해 보았는데, 과연 워터마크가 전혀 없었습니다. 🎜rrreee🎜워터마크 링크 없음
그렇습니다 Douyin의 워터마크 제거가 너무 간단하고 감동적이라는 것을 알았습니다. 하하하~🎜🎜🎜🎜직접 연습해 보세요🎜🎜이제 원리가 명확해졌으니, 단계별로 기능을 구현하는 일만 남았습니다. 매우 간단한 것 같지만 구현 시 여전히 몇 가지 작은 함정에 직면하여 많은 시간을 낭비했습니다. 🎜🎜구현 과정에는 세 가지 간단한 단계만 있습니다: 🎜
  • 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
@Controllerpublic 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了。

Java 프로그래머가 Douyin 비디오 워터마크 제거 도구를 직접 작성했습니다.

为快速实现我用了老古董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: `<p></p><p></p><p><a><button>下载视频</button></a></p><p><textarea>${rows['videoUrl']}</textarea><button>复制链接</button></p><p><a><button>下载音频</button></a></p><video><source> </source></video>`
                //content: `<video><source> </source></video>`
            });

        } 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,页面中设置如下参数。

 <!-- 解决访问视频url 请求403异常 -->
 <meta>

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

Java 프로그래머가 Douyin 비디오 워터마크 제거 도구를 직접 작성했습니다.

总结

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

위 내용은 Java 프로그래머가 Douyin 비디오 워터마크 제거 도구를 직접 작성했습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 learnku.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제