溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

java程序員如何手寫一個(gè)抖音視頻去水印工具

發(fā)布時(shí)間:2020-11-30 10:58:35 來源:億速云 閱讀:432 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關(guān)java程序員如何手寫一個(gè)抖音視頻去水印工具的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考。一起跟隨小編過來看看吧。

java基礎(chǔ)欄目介紹去水印工具的方法。

百因必有果

說一下我為什么要做個(gè)抖音視頻去水印工具,其實(shí)是因?yàn)槲业纳车衽?,她居然剛我~

有天晚上她在抖音看見一個(gè)非常具有 教育意義 的視頻,“男人疼媳婦就該承包全部家務(wù)活”,然后它就想把視頻下載下來,分享到她的姐妹群交流 馭夫 心得。

可是大家都知道抖音下載的視頻是帶水印,作為一個(gè)重度強(qiáng)迫癥選手這是不被允許的,沒辦法那就找找有沒有去水印工具吧,找了一圈要不就是收費(fèi),要么下載不下來,主上臉上的笑容也在逐漸消失。

我在邊上調(diào)侃了一句:也沒多難,要不我給你做一個(gè)!“你行嗎?” 然后投來了一個(gè)不屑的眼神。

java程序員如何手寫一個(gè)抖音視頻去水印工具

哎呀!本來就開個(gè)玩笑,居然說我不行,這就不能忍了,我得證明給你看看!男人嘛,就受不了這話

先看下我做的去水印工具線上預(yù)覽效果: 47.93.6.5:8888/index

java程序員如何手寫一個(gè)抖音視頻去水印工具

下邊和大家一起分析下做這個(gè)去水印工具的思路,很多人乍一聽 去水印 ,下意識(shí)的覺得是一種什么牛比的算法,其實(shí)這是一種假象~

刨根問底

雖說要爭口氣,可剛開始做的時(shí)候我也真是一臉懵逼,因?yàn)楦静恢涝搹哪娜胧?,去水印什么原理?。侩y不成我還要寫個(gè)算法?

找了一個(gè)抖音視頻的分享鏈接,一點(diǎn)點(diǎn)分析,不難發(fā)現(xiàn)這是個(gè)經(jīng)過處理的短鏈接,那這個(gè)短鏈接一定會(huì)重定向到真實(shí)的視頻地址 URL 。

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

瀏覽器中輸入短鏈接得到了下邊這個(gè) URL ,以我的經(jīng)驗(yàn)判斷URL中的 6820792802394262795 很有可能是視頻的唯一ID,而唯一ID通常用來作為獲取詳情接口的入?yún)?,哎嘿~ 好像有點(diǎn)頭緒了。

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

java程序員如何手寫一個(gè)抖音視頻去水印工具

趕緊祭出 F12 大法打開控制臺(tái),在眾多請(qǐng)求中發(fā)現(xiàn)這么一個(gè)接口,它居然用到了上邊的唯一ID。

https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=6820792802394262795

java程序員如何手寫一個(gè)抖音視頻去水印工具
更驚喜的是接口返回的數(shù)據(jù)那叫一個(gè)詳細(xì),作者信息、音頻地址、視頻地址、平面圖都有。但唯獨(dú)沒有無水印的視頻 URL。
java程序員如何手寫一個(gè)抖音視頻去水印工具
只找到一個(gè)有水印的視頻 URL,有點(diǎn)小失落,我又看了看這個(gè)地址,發(fā)現(xiàn) wm 和我項(xiàng)目名有點(diǎn)像啊,不就是watermark 水印的縮寫嗎?

https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f030000bqk54kg2saj3lso3oh30&ratio=720p&line=0

java程序員如何手寫一個(gè)抖音視頻去水印工具
好像又看到了一絲希望,我趕緊修改URL在瀏覽器中又試了一下,果然真的沒水印了。

https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200f030000bqk54kg2saj3lso3oh30&ratio=720p&line=0

java程序員如何手寫一個(gè)抖音視頻去水印工具
到這才發(fā)現(xiàn)抖音去水印 簡單的讓人感動(dòng),哈哈哈~

身體力行

既然原理都清晰了,剩下的就是一步一步實(shí)現(xiàn)功能了,原理看著挺簡單的,但實(shí)現(xiàn)中還是遇到一點(diǎn)點(diǎn)小坑,浪費(fèi)了不少時(shí)間。

實(shí)現(xiàn)過程只有簡單的三步:

  • 1、從輸入框中過濾取出視頻短連接

  • 2、短連接傳到后端解析出無水印的視頻 URL

  • 3、視頻 URL傳遞給前端預(yù)覽、下載

后端并沒有什么難度,一步一步按照上邊分析的流程解析真實(shí)視頻 URL 就可以了。

注意 :我們想得到的地址URL,都是當(dāng)前短連接URL 經(jīng)過重定向后的URL。而抖音有些鏈接是不支持瀏覽器訪問的,所以要手動(dòng)修改 User-agent 屬性模擬移動(dòng)端訪問才可以。

/**
* @param url
* @author xiaofu
* @description 獲取當(dāng)前鏈接重定向后的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");//模擬手機(jī)連接
            conn.connect();
            String location = conn.getHeaderField("Location");
            return location;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

下邊是完整的后端實(shí)現(xiàn),可以看到代碼量非常的少。

/**
 * @author xiaofu-公眾號(hào):程序員內(nèi)點(diǎn)事
 * @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、拿到視頻對(duì)應(yīng)的 ItemId
             */
            String videoUrl = "";
            String musicUrl = "";
            String videoPic = "";
            String desc = "";
            if (!StringUtils.isEmpty(redirectUrl)) {
                /**
                 * 3、用 ItemId 拿視頻的詳細(xì)信息,包括無水印視頻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);
    }}

前端實(shí)現(xiàn)也比較簡單,拿到后端解析出來的視頻URL 預(yù)覽播放、下載就OK了。

java程序員如何手寫一個(gè)抖音視頻去水印工具

為快速實(shí)現(xiàn)我用了老古董JQuery,我這個(gè)年紀(jì)的人對(duì)它感情還是很深厚的,UI 框架用的 layer.js。源碼后邊會(huì)分享給大家,就不全貼出來了。

$.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 style="overflow:hidden;height: 580px;width: 350px;"><p><p class="popButton"><a href="###" rel="noopener nofollow noreferrer" onclick="downloadVideo('${rows['videoUrl']}','${rows['desc']}')"><button class="layui-bg-red layui-btn-sm layui-btn">下載視頻</button></a></p><p class="popButton"><textarea id="videourl" cols="1" rows="1" style="height:0;width:0;position: absolute;">${rows['videoUrl']}</textarea><button class="layui-btn-sm layui-bg-blue layui-btn" onclick="copy('videourl')">復(fù)制鏈接</button></p><p class="popButton"><a href="###" rel="noopener nofollow noreferrer" onclick="downloadVideo('${rows['musicUrl']}','${rows['desc']}')"><button class="layui-btn-sm layui-btn">下載音頻</button></a></p><video id="video" width="360px" height="500px" src="${rows['videoUrl']}" controls = "true" poster="${rows['videoPic']}" preload="auto" webkit-playsinline="true" playsinline="true" x-webkit-airplay="allow" x5-video-player-type="h6" x5-video-player-fullscreen="true" x5-video-orientation="portraint" style="object-fit:fill"><source src="${rows['videoUrl']}" type="video/mp4"> </video></p></p>`
                //content: `<video id="video" src="${rows['videoUrl']}" controls = "true" poster="${rows['videoPic']}" preload="auto" webkit-playsinline="true" playsinline="true" x-webkit-airplay="allow" x5-video-player-type="h6" x5-video-player-fullscreen="true" x5-video-orientation="portraint" style="object-fit:fill"><source src="${rows['videoUrl']}" type="video/mp4"> </video>`
            });

        } catch (error) {
            layer.alert('錯(cuò)誤信息:' + error, {
                title: '異常',
                skin: 'layui-layer-lan',
                closeBtn: 0,
                anim: 4 //動(dòng)畫類型
            });
            return false;
        }
    },
    error: function (err) {
        console.log(err);
        layer.close(index);
        $('.qsy-submit').attr('disabled', false);
    },
    done: function () {
        layer.close(index);
    }})})

注意:我們?cè)谧约旱木W(wǎng)站中引用其它網(wǎng)站的資源URL,由于不在同一個(gè)域名下referrer 不同,通常會(huì)遇到三方網(wǎng)站的防盜鏈攔截,所以要想正常訪問三方資源,必須要隱藏請(qǐng)求的referrer,頁面中設(shè)置如下參數(shù)。

 <!-- 解決訪問視頻url 請(qǐng)求403異常 -->
 <meta name="referrer" content="no-referrer"/>

還簡單做了下移動(dòng)端適配,樣式看著還可以,但是功能使用起來有點(diǎn)差強(qiáng)人意,后邊在做優(yōu)化了。

java程序員如何手寫一個(gè)抖音視頻去水印工具

感謝各位的閱讀!關(guān)于java程序員如何手寫一個(gè)抖音視頻去水印工具就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI