zoukankan      html  css  js  c++  java
  • 视频剪辑去除水印小工具

    零、直接下载

    百度网盘链接:https://pan.baidu.com/s/1b8IvB4q-e2VVWR2uKikuQQ

    提取码:1edz

    解压,双击运行RemoveWatermark.exe即可使用。


    一、背景

    现在B站越来越火,需要用到视频剪辑工具,我也试了几款免费的视频剪辑工具,发现免费试用,不成为会员,都会给你的视频加上水印。我平时不怎么使用视频剪辑,就偶尔用一下,因此,我就想着要去除水印,因此开发了这款小工具。

    二、实现思路

    1、因为视频剪辑软件的水印基本都打在上方,有如下情况:

    水印1  水印3

    首先要把原图像往上拓展一些黑色区域,得到如下效果:

    步骤1

    2、把预处理好的视频送到视频剪辑软件处理,水印就打在拓展区域上了:

    步骤2

    3、对打上水印的视频进行后处理,把带水印的上方区域裁切掉,就得到去水印后的效果:

    步骤3

    三、代码实现:

    开发环境:win10 + QT5.7.1

    依赖库:opencv3.1.0 + ffmpeg-4.3

    1、pro工程设置

    #opencv
    INCLUDEPATH += C:Opencv3.1.0opencvuildincludeopencv
                C:Opencv3.1.0opencvuildincludeopencv2
                C:Opencv3.1.0opencvuildinclude
    LIBS += C:Opencv3.1.0opencvuildx64vc14libopencv_world310.lib
    
    #ffmpeg
    INCLUDEPATH += D:3rdPartyffmpeg-4.3ffmpeg-4.3-win64-devinclude
    LIBS += D:3rdPartyffmpeg-4.3ffmpeg-4.3-win64-devlib*.lib

    2、预处理(区域拓展)代码片段

    cv::VideoWriter writer(preSaveName.toStdString(), CV_FOURCC('M', 'J', 'P', 'G'), 30, cv::Size(width, heightExtern));//
        cv::Mat frame;
        cv::Mat frameExtern = cv::Mat::zeros(heightExtern, width, CV_8UC3);
    
        while (1)
        {
            cap >> frame;
            if (frame.empty())
            {
                break;
            }
            frame.copyTo(frameExtern(rect));
            //cv::inpaint(frame, mask, frame, 7.0, cv::INPAINT_TELEA);
            writer << frameExtern;
            cv::imshow("frame", frameExtern);
            cv::waitKey(10);
        }
        cap.release();

    3、后处理(crop)代码片段

        av_register_all();  //ffmpeg程序的第一句,注册库
    
        AVFormatContext *afc = NULL;
        int width = 0;
        int height = 0;
        int time_length = 0;
    
        //打开视频文件
        int nRet = avformat_open_input(&afc, inputFileName.c_str(), 0, 0);
        if (nRet < 0)
        {
            std::cout << "can't find file!" << std::endl;
        }
        else
        {
            std::cout << "open file success!" << std::endl;
        }
        int durTime = afc->duration / AV_TIME_BASE;  //视频时间 4分20秒
        std::cout << "durTime = " << durTime << std::endl;
        unsigned int numberOfStream = afc->nb_streams;  //包含流的个数2:一个视频流一个音频流
        std::cout << "numberOfStream = " << numberOfStream << std::endl;
    
        for (int i = 0; i < afc->nb_streams; i++)
        {
            AVCodecContext *acc = afc->streams[i]->codec;
            if (acc->codec_type == AVMEDIA_TYPE_VIDEO)  //如果是视频类型
            {
                std::cout << "AVMEDIA_TYPE_VIDEO" << std::endl;
                AVCodec *codec = avcodec_find_decoder(acc->codec_id);
                if (!codec)
                {
                    std::cout << "no decoder!" << std::endl;
                }
                width = acc->width;
                height = acc->height;
                std::cout << "width = " << width << ", height = " << height << std::endl;
    
                int ret = avcodec_open2(acc, codec, NULL);
                if (ret != 0)
                {
                    char buf[1024] = { 0 };
                    av_strerror(ret, buf, sizeof(buf));
                }
    
                std::cout << "open decoder success!" << std::endl;
            }
            if (acc->codec_type == AVMEDIA_TYPE_AUDIO)
            {
                std::cout << "AVMEDIA_TYPE_AUDIO" << std::endl;
            }
        }
    
        if (afc)
        {
            std::cout << "avformat_close_input" << std::endl;
            avformat_close_input(&afc);  //关闭视频流
            std::cout << "avformat_close_input close" << std::endl;
        }
    
        //处理
        int x = 0;
        int y = height*0.2;
        time_length = durTime - 5;//去除最后5s的视频
        char cmd[128] = { 0 };
        //crop
        sprintf(cmd, "ffmpeg -i %s -vf crop='1280:720:%d:%d' -acodec copy %s", inputFileName.c_str(), x, y, outputFileName.c_str());
        //crop,去除尾部
        //sprintf(cmd, "ffmpeg -i expand_miao.mp4 -vf crop='1280:720:%d:%d' -acodec copy -ss 00:00:00 -t %d remove_water2.mp4", x, y, time_length);
        std::string str = cmd;
        std::cout << "str = " << str << std::endl;
        system(cmd);

    四、使用场景

    该小工具适用于所有水印在上方的情况。

    五、界面

    image image

    六、使用步骤

    1、使用小工具先进行预处理

    (1)点击“视频文件导入”按钮,选择原始视频;

    (2)设置输出文件名,默认存放在D盘根目录下,avi格式(现在暂时只支持这种格式);

    (3)点击开始预处理按钮,等待处理完成。

    2、视频剪辑软件处理

    3、使用小工具进行后处理

    (1)点击“视频文件导入”按钮,选择视频剪辑软件处理好的视频;

    (2)设置输出文件名,默认存放在D盘根目录下,可以支持mp4格式;

    (3)点击开始后处理按钮,等待处理完成。

    七、小工具下载地址

    如果不想自己开发,我也提供了编译好的小工具,供大家下载使用:

    百度网盘链接:https://pan.baidu.com/s/1b8IvB4q-e2VVWR2uKikuQQ

    提取码:1edz

    解压,双击运行RemoveWatermark.exe即可使用。

    end

  • 相关阅读:
    Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析
    Linq分区操作之Skip,SkipWhile,Take,TakeWhile源码分析
    Linq生成操作之DefautIfEmpty,Empty,Range,Repeat源码分析
    Linq基础操作之Select,Where,OrderBy,ThenBy源码分析
    PAT 1152 Google Recruitment
    PAT 1092 To Buy or Not to Buy
    PAT 1081 Rational Sum
    PAT 1084 Broken Keyboard
    PAT 1077 Kuchiguse
    PAT 1073 Scientific Notation
  • 原文地址:https://www.cnblogs.com/smbx-ztbz/p/13309517.html
Copyright © 2011-2022 走看看