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

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

Nov 27, 2020 pm 05:02 PM
java 워터마크 제거

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

자바의 제곱근 자바의 제곱근 Aug 30, 2024 pm 04:26 PM

자바의 제곱근 안내 여기서는 예제와 코드 구현을 통해 Java에서 Square Root가 어떻게 작동하는지 설명합니다.

자바의 완전수 자바의 완전수 Aug 30, 2024 pm 04:28 PM

Java의 완전수 가이드. 여기서는 정의, Java에서 완전 숫자를 확인하는 방법, 코드 구현 예제에 대해 논의합니다.

Java의 난수 생성기 Java의 난수 생성기 Aug 30, 2024 pm 04:27 PM

Java의 난수 생성기 안내. 여기서는 예제를 통해 Java의 함수와 예제를 통해 두 가지 다른 생성기에 대해 설명합니다.

자바의 암스트롱 번호 자바의 암스트롱 번호 Aug 30, 2024 pm 04:26 PM

자바의 암스트롱 번호 안내 여기에서는 일부 코드와 함께 Java의 Armstrong 번호에 대한 소개를 논의합니다.

자바의 웨카 자바의 웨카 Aug 30, 2024 pm 04:28 PM

Java의 Weka 가이드. 여기에서는 소개, weka java 사용 방법, 플랫폼 유형 및 장점을 예제와 함께 설명합니다.

Java의 스미스 번호 Java의 스미스 번호 Aug 30, 2024 pm 04:28 PM

Java의 Smith Number 가이드. 여기서는 정의, Java에서 스미스 번호를 확인하는 방법에 대해 논의합니다. 코드 구현의 예.

Java Spring 인터뷰 질문 Java Spring 인터뷰 질문 Aug 30, 2024 pm 04:29 PM

이 기사에서는 가장 많이 묻는 Java Spring 면접 질문과 자세한 답변을 보관했습니다. 그래야 면접에 합격할 수 있습니다.

Java 8 Stream foreach에서 나누거나 돌아 오시겠습니까? Java 8 Stream foreach에서 나누거나 돌아 오시겠습니까? Feb 07, 2025 pm 12:09 PM

Java 8은 스트림 API를 소개하여 데이터 컬렉션을 처리하는 강력하고 표현적인 방법을 제공합니다. 그러나 스트림을 사용할 때 일반적인 질문은 다음과 같은 것입니다. 기존 루프는 조기 중단 또는 반환을 허용하지만 스트림의 Foreach 메소드는이 방법을 직접 지원하지 않습니다. 이 기사는 이유를 설명하고 스트림 처리 시스템에서 조기 종료를 구현하기위한 대체 방법을 탐색합니다. 추가 읽기 : Java Stream API 개선 스트림 foreach를 이해하십시오 Foreach 메소드는 스트림의 각 요소에서 하나의 작업을 수행하는 터미널 작동입니다. 디자인 의도입니다

See all articles