Рукописный инструмент Douyin для создания водяных знаков на видео, не будьте просто программистом

Java задняя часть
Рукописный инструмент Douyin для создания водяных знаков на видео, не будьте просто программистом

Сто причин должны принести плоды

Скажи мне, почему я хочу сделать инструмент для нанесения водяных знаков на видео Douyin, на самом деле это из-за моей подруги-скульптуры из песка, она просто я~

Однажды ночью на Дуине она увидела очень教育意义видео "Мужчина, который любит свою невестку, должен делать всю работу по дому", а затем она хочет скачать видео и поделиться им со своей сестринской группой для общения驭夫опыт.

Но все знают, что видео, скачанное Douyin, имеет водяные знаки. Как игроку с тяжелым обсессивно-компульсивным расстройством, это запрещено. Если нет возможности, то узнайте, есть ли инструмент для удаления водяных знаков. будет либо заряжать, либо скачивать.Не сходит,улыбка на лице Господа постепенно исчезает.

Я пошутил на стороне: это не так уж сложно, или я сделаю его для вас! - Ты в порядке? - Затем он бросил презрительный взгляд.

在这里插入图片描述

Ой! Я просто пошутил, а на самом деле сказал, что не могу этого сделать, это невыносимо, я должен тебе это доказать! чувак, терпеть не могу

Давайте посмотрим на эффект онлайн-предварительного просмотра инструмента для удаления водяных знаков, который я сделал:http://47.93.6.5:8888/index

去水印使用预览

Ниже я разберу идею сделать этот инструмент для водяных знаков со всеми, многие люди слышат это с первого взгляда.去水印, я подсознательно думаю, что это какой-то алгоритм, но на самом деле это иллюзия~

Докопаться до сути вещей

Хотя мне и приходится бороться, я очень растерялся, когда впервые начал это делать, потому что не знал, с чего начать, и по какому принципу снимать водяной знак? Возможно ли, что я должен написать алгоритм?

Я нашел ссылку для обмена видео Douyin, и после небольшого анализа нетрудно обнаружить, что это обработанная короткая ссылка, тогда эта короткая ссылка обязательно перенаправит на реальный адрес видеоURL.

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

Введите короткую ссылку в браузере и получите следующееURL, судя по моему опытуURLсередина6820792802394262795Скорее всего, это уникальный идентификатор видео, а уникальный идентификатор обычно используется в качестве входного параметра для получения подробного интерфейса, хе-хе~ Кажется, я понял.

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

有水印的链接

быстро пожертвоватьF12Дафа открыл консоль и среди множества запросов обнаружил такой интерфейс, который на самом деле использовал указанный выше уникальный идентификатор.

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

无水印链接Только что нашел TikTok здесь去水印Это просто и трогательно, хахаха~

упражняться

Теперь, когда принцип ясен, осталось реализовать функцию шаг за шагом.Принцип выглядит очень просто, но в реализации все еще есть небольшие ямки, на что уходит много времени.

Процесс внедрения состоит всего из трех простых шагов:

  • 1. Отфильтруйте короткую ссылку на видео из поля ввода.
  • 2. Короткое соединение отправляется на серверную часть для анализа видео без водяных знаков.URL
  • 3. ВидеоURLПерешел на предварительный просмотр, скачать

В задней части нет никаких сложностей, шаг за шагом анализировать реальное видео в соответствии с описанным выше процессом анализа.URLВот и все.

Уведомление: адрес, который мы хотим получитьURL, все текущие короткие соединенияURLпосле перенаправленияURL. Некоторые ссылки Douyin не поддерживают доступ через браузер, поэтому их необходимо изменить вручную.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Предварительное воспроизведение, загрузка в порядке.

在这里插入图片描述

Для быстрой реализации я использовал антиквариат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: `<div style="overflow:hidden;height: 580px;width: 350px;"><div><div 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></div><div 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')">复制链接</button></div><div class="popButton"><a href="###" rel="noopener nofollow noreferrer" onclick="downloadVideo('${rows['musicUrl']}','${rows['desc']}')"><button class="layui-btn-sm layui-btn">下载音频</button></a></div><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="h5" x5-video-player-fullscreen="true" x5-video-orientation="portraint" style="object-fit:fill"><source src="${rows['videoUrl']}" type="video/mp4"> </video></div></div>`
                //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="h5" 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('错误信息:' + 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 name="referrer" content="no-referrer"/>

Я также просто сделал адаптацию мобильного терминала, стиль выглядит хорошо, но функция немного неудовлетворительна в использовании, и оптимизация будет сделана позже.

在这里插入图片描述

Суммировать

Таких вещей много. Пока я не изучаю их серьезно, я всегда чувствую себя непостижимым. Однако, как только я соприкасаюсь с сутью техники, я начинаю смеяться над собой за то, что я глуп. Понимаю я это или нет, я иногда проверяйте слой оконной бумаги.

Ну вот и все на сегодня, исходный код этой статьи находится по адресуМой официальный аккаунт [Внутренние дела программиста] Ответить [исходный код】 Самовывоз


Разобраны и розданы друзьям сотни различных технических электронных книг. Подпишитесь на официальный аккаунт, чтобы ответить [666], чтобы получить его самостоятельно. Мы создали группу технического обмена с друзьями, чтобы обсуждать технологии и делиться технической информацией, стремясь вместе учиться и развиваться. Если вам интересно, присоединяйтесь к нам!