| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 715 人关注过本帖, 1 人收藏
标题:求助:VS2022和FFmpeg如何开发出视频剪辑软件。。。
只看楼主 加入收藏
追梦人zmrghy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:406
专家分:190
注 册:2021-4-9
结帖率:97.26%
收藏(1)
已结贴  问题点数:20 回复次数:6 
求助:VS2022和FFmpeg如何开发出视频剪辑软件。。。
要求,可以播放 ,上一帧,下一帧、拆分。。
可以支持帧的精确剪辑。。。
系统照片->视频编辑器可以支持帧的精确剪辑。。
但是,视频编辑器导出视频时,,视频宽,高,帧率都会改变,这一点很不好用。。。。


图片附件: 游客没有浏览图片的权限,请 登录注册



自己如何使用VS2022和FFmpeg 开发剪辑软件。。。
求详细思路,最好可以画出流程图。。。。
搜索更多相关主题的帖子: 视频 编辑器 软件  开发 
2023-04-05 02:27
东海ECS
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:Python
等 级:版主
威 望:32
帖 子:412
专家分:1646
注 册:2023-1-24
收藏
得分:8 
以下是一个简单的视频播放器的代码示例,可供参考:
程序代码:
#include <iostream>
#include <string>
#include <thread>
#include "SDL.h"
#include "SDL_thread.h"
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}
const int kVideoWidth = 640;
const int kVideoHeight = 360;
const std::string kVideoPath = "test.mp4";
int main(int argc, char* argv[])
{
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
    {
        std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl;
        return -1;
    }
    AVFormatContext* format_context = avformat_alloc_context();
    if (avformat_open_input(&format_context, kVideoPath.c_str(), nullptr, nullptr) != 0)
    {
        std::cerr << "Failed to open video file: " << kVideoPath << std::endl;
        return -1;
    }
    if (avformat_find_stream_info(format_context, nullptr) < 0)
    {
        std::cerr << "Failed to find video stream information" << std::endl;
        return -1;
    }
    AVCodec* codec = nullptr;
    int stream_index = -1;
    for (int i = 0; i < format_context->nb_streams; i++)
    {
        if (format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            codec = avcodec_find_decoder(format_context->streams[i]->codecpar->codec_id);
            stream_index = i;
            break;
        }
    }
    if (codec == nullptr)
    {
        std::cerr << "Failed to find video codec" << std::endl;
        return -1;
    }
    AVCodecContext* codec_context = avcodec_alloc_context3(codec);
    if (avcodec_parameters_to_context(codec_context, format_context->streams[stream_index]->codecpar) < 0)
    {
        std::cerr << "Failed to copy video codec parameters to context" << std::endl;
        return -1;
    }
    if (avcodec_open2(codec_context, codec, nullptr) < 0)
    {
        std::cerr << "Failed to open video codec" << std::endl;
        return -1;
    }
    AVFrame* frame = av_frame_alloc();
    AVFrame* frame_rgb = av_frame_alloc();
    uint8_t* buffer = nullptr;
    int buffer_size = 0;
    buffer_size = av_image_get_buffer_size(AV_PIX_FMT_RGB24, kVideoWidth, kVideoHeight, 1);
    buffer = reinterpret_cast<uint8_t*>(av_malloc(buffer_size));
    av_image_fill_arrays(frame_rgb->data, frame_rgb->linesize, buffer, AV_PIX_FMT_RGB24, kVideoWidth, kVideoHeight, 1);
    struct SwsContext* sws_context = sws_getContext(codec_context->width, codec_context->height, codec_context->pix_fmt, kVideoWidth, kVideoHeight, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
    SDL_Window* window = SDL_CreateWindow("Video Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, kVideoWidth, kVideoHeight, SDL_WINDOW_OPENGL);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, kVideoWidth, kVideoHeight);
    AVPacket packet;
    bool is_running = true;
    while (av_read_frame(format_context, &packet) >= 0 && is_running)
    {
        if (packet.stream_index == stream_index)
        {
            if (avcodec_send_packet(codec_context, &packet) == 0)
            {
                while (avcodec_receive_frame(codec_context, frame) == 0)
                {
                    sws_scale(sws_context, frame->data, frame->linesize, 0, codec_context->height, frame_rgb->data, frame_rgb->linesize);
                    SDL_UpdateTexture(texture, nullptr, frame_rgb->data[0], frame_rgb->linesize[0]);
                    SDL_RenderClear(renderer);
                    SDL_RenderCopy(renderer, texture, nullptr, nullptr);
                    SDL_RenderPresent(renderer);
                    SDL_Event event;
                    while (SDL_PollEvent(&event))
                    {
                        if (event.type == SDL_QUIT)
                        {
                            is_running = false;
                            break;
                        }
                    }
                }
            }
        }
        av_packet_unref(&packet);
    }
    av_frame_free(&frame);
    av_frame_free(&frame_rgb);
    avcodec_close(codec_context);
    avformat_close_input(&format_context);
    avformat_free_context(format_context);
    av_free(buffer);
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}

会当凌绝顶,一览众山小.
2023-04-05 12:19
东海ECS
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:Python
等 级:版主
威 望:32
帖 子:412
专家分:1646
注 册:2023-1-24
收藏
得分:8 
以下是一个基于FFmpeg库的简单视频剪辑代码示例,实现了将指定时间段内的视频裁剪并保存为新的视频文件
程序代码:
#include <iostream>
#include <string>
#include <thread>
#include "SDL.h"
#include "SDL_thread.h"
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}
const int kVideoWidth = 640;
const int kVideoHeight = 360;
const std::string kVideoPath = "test.mp4";
const std::string kOutputPath = "output.mp4";
const int kStartTime = 5; // 单位:秒
const int kEndTime = 10;  // 单位:秒
int main(int argc, char* argv[])
{
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
    {
        std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl;
        return -1;
    }
    AVFormatContext* format_context = avformat_alloc_context();
    if (avformat_open_input(&format_context, kVideoPath.c_str(), nullptr, nullptr) != 0)
    {
        std::cerr << "Failed to open video file: " << kVideoPath << std::endl;
        return -1;
    }
    if (avformat_find_stream_info(format_context, nullptr) < 0)
    {
        std::cerr << "Failed to find video stream information" << std::endl;
        return -1;
    }
    AVCodec* codec = nullptr;
    int stream_index = -1;
    for (int i = 0; i < format_context->nb_streams; i++)
    {
        if (format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            codec = avcodec_find_decoder(format_context->streams[i]->codecpar->codec_id);
            stream_index = i;
            break;
        }
    }
    if (codec == nullptr)
    {
        std::cerr << "Failed to find video codec" << std::endl;
        return -1;
    }
    AVCodecContext* codec_context = avcodec_alloc_context3(codec);
    if (avcodec_parameters_to_context(codec_context, format_context->streams[stream_index]->codecpar) < 0)
    {
        std::cerr << "Failed to copy video codec parameters to context" << std::endl;
        return -1;
    }
    if (avcodec_open2(codec_context, codec, nullptr) < 0)
    {
        std::cerr << "Failed to open video codec" << std::endl;
        return -1;
    }
    AVFrame* frame = av_frame_alloc();
    AVFrame* frame_rgb = av_frame_alloc();
    uint8_t* buffer = nullptr;
    int buffer_size = 0;
    buffer_size = av_image_get_buffer_size(AV_PIX_FMT_RGB24, kVideoWidth, kVideoHeight, 1);
    buffer = reinterpret_cast<uint8_t*>(av_malloc(buffer_size));
    av_image_fill_arrays(frame_rgb->data, frame_rgb->linesize, buffer, AV_PIX_FMT_RGB24, kVideoWidth, kVideoHeight, 1);
    struct SwsContext* sws_context = sws_getContext(codec_context->width, codec_context->height, codec_context->pix_fmt, kVideoWidth, kVideoHeight, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
    SDL_Window* window = SDL_CreateWindow("Video Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, kVideoWidth, kVideoHeight, SDL_WINDOW_OPENGL);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, kVideoWidth, kVideoHeight);
    AVPacket packet;
    AVFormatContext* output_format_context = nullptr;
    if (avformat_alloc_output_context2(&output_format_context, nullptr, nullptr, kOutputPath.c_str()) < 0)
    {
        std::cerr << "Failed to allocate output format context" << std::endl;
        return -1;
    }
    AVStream* output_stream = avformat_new_stream(output_format_context, codec);
    if (output_stream == nullptr)
    {
        std::cerr << "Failed to allocate output stream" << std::endl;
        return -1;
    }
    if (avcodec_parameters_copy(output_stream->codecpar, format_context->streams[stream_index]->codecpar) < 0)
    {
        std::cerr << "Failed to copy codec parameters to output stream" << std::endl;
        return -1;
    }
    output_stream->time_base = format_context->streams[stream_index]->time_base;
    if (!(output_format_context->oformat->flags & AVFMT_NOFILE))
    {
        if (avio_open(&output_format_context->pb, kOutputPath.c_str(), AVIO_FLAG_WRITE) < 0)
        {
            std::cerr << "Failed to open output file" << std::endl;
            return -1;
        }
    }
    if (avformat_write_header(output_format_context, nullptr) < 0)
    {
        std::cerr << "Failed to write output file header" << std::endl;
        return -1;
    }
    bool is_running = true;
    int64_t start_pts = kStartTime * AV_TIME_BASE;
    int64_t end_pts = kEndTime * AV_TIME_BASE;
    while (av_read_frame(format_context, &packet) >= 0 && is_running)
    {
        if (packet.stream_index == stream_index)
        {
            if (avcodec_send_packet(codec_context, &packet) == 0)
            {
                while (avcodec_receive_frame(codec_context, frame) == 0)
                {
                    if (frame->pts >= start_pts && frame->pts <= end_pts)
                    {
                        sws_scale(sws_context, frame->data, frame->linesize, 0, codec_context->height, frame_rgb->data, frame_rgb->linesize);
                        SDL_UpdateTexture(texture, nullptr, frame_rgb->data[0], frame_rgb->linesize[0]);
                        SDL_RenderClear(renderer);
                        SDL_RenderCopy(renderer, texture, nullptr, nullptr);
                        SDL_RenderPresent(renderer);
                        if (av_write_frame(output_format_context, &packet) < 0)
                        {
                            std::cerr << "Failed to write frame to output file" << std::endl;
                            return -1;
                        }
                        if (av_gettime_relative() >= end_pts)
                        {
                            is_running = false;
                            break;
                        }
                    }
                }
            }
        }
        av_packet_unref(&packet);
    }
    av_write_trailer(output_format_context);
    av_frame_free(&frame);
    av_frame_free(&frame_rgb);
    avcodec_close(codec_context);
    avformat_close_input(&format_context);
    avformat_free_context(format_context);
    av_free(buffer);
    avio_close(output_format_context->pb);
    avformat_free_context(output_format_context);
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}

会当凌绝顶,一览众山小.
2023-04-05 12:22
东海ECS
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:Python
等 级:版主
威 望:32
帖 子:412
专家分:1646
注 册:2023-1-24
收藏
得分:4 
由于视频剪辑涉及到的功能较为复杂,代码实现难度较大,因此无法为您编写.我可以给您一些建议:

使用FFmpeg库来开发视频剪辑软件,需要编写C++代码。可以使用FFmpeg提供的API来实现视频的读取、播放、剪辑等功能。具体代码实现过程可以参考FFmpeg官方文档和示例代码。

要实现视频播放功能,可以使用FFmpeg的AVCodecContext和AVFrame等结构体来读取视频帧数据,并使用SDL或OpenGL等库来实现视频的渲染。

要实现视频剪辑功能,需要对视频帧数据进行处理。可以使用FFmpeg提供的API来裁剪、拆分、合并视频帧数据,从而实现精确剪辑功能。

为了方便操作,需要实现一个简单的界面。可以使用Windows窗口或Qt等跨平台UI框架来实现界面交互。

完成代码编写后,需要进行测试和优化。可以使用各种测试数据和场景来检验软件的稳定性和性能,从而进行优化和改进。

会当凌绝顶,一览众山小.
2023-04-05 12:26
东海ECS
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:Python
等 级:版主
威 望:32
帖 子:412
专家分:1646
注 册:2023-1-24
收藏
得分:0 
上面的两段代码是我学习的时候写的,这里贴出来,可以给您参考🐶

会当凌绝顶,一览众山小.
2023-04-05 12:30
追梦人zmrghy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:406
专家分:190
注 册:2021-4-9
收藏
得分:0 
回复 5楼 东海ECS
程序代码:
#include <iostream>
#include <string>
#include <thread>
#include "SDL2/SDL.h"
#include "SDL2/SDL_thread.h"
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
#include "libavutil/time.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}
const int kVideoWidth = 640;
const int kVideoHeight = 360;
const std::string kVideoPath = "test.mp4";
const std::string kOutputPath = "output.mp4";
const int kStartTime = 5; // 单位:秒
const int kEndTime = 10;  // 单位:秒
int main(int argc, char* argv[])
{
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
    {
        std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl;
        return -1;
    }
    AVFormatContext* format_context = avformat_alloc_context();
    if (avformat_open_input(&format_context, kVideoPath.c_str(), nullptr, nullptr) != 0)
    {
        std::cerr << "Failed to open video file: " << kVideoPath << std::endl;
        return -1;
    }
    if (avformat_find_stream_info(format_context, nullptr) < 0)
    {
        std::cerr << "Failed to find video stream information" << std::endl;
        return -1;
    }
    const AVCodec* codec = nullptr;
    int stream_index = -1;
    for (int i = 0; i < format_context->nb_streams; i++)
    {
        if (format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            codec = avcodec_find_decoder(format_context->streams[i]->codecpar->codec_id);
            stream_index = i;
            break;
        }
    }
    if (codec == nullptr)
    {
        std::cerr << "Failed to find video codec" << std::endl;
        return -1;
    }
    AVCodecContext* codec_context = avcodec_alloc_context3(codec);
    if (avcodec_parameters_to_context(codec_context, format_context->streams[stream_index]->codecpar) < 0)
    {
        std::cerr << "Failed to copy video codec parameters to context" << std::endl;
        return -1;
    }
    if (avcodec_open2(codec_context, codec, nullptr) < 0)
    {
        std::cerr << "Failed to open video codec" << std::endl;
        return -1;
    }
    AVFrame* frame = av_frame_alloc();
    AVFrame* frame_rgb = av_frame_alloc();
    uint8_t* buffer = nullptr;
    int buffer_size = 0;
    buffer_size = av_image_get_buffer_size(AV_PIX_FMT_RGB24, kVideoWidth, kVideoHeight, 1);
    buffer = reinterpret_cast<uint8_t*>(av_malloc(buffer_size));
    av_image_fill_arrays(frame_rgb->data, frame_rgb->linesize, buffer, AV_PIX_FMT_RGB24, kVideoWidth, kVideoHeight, 1);
    struct SwsContext* sws_context = sws_getContext(codec_context->width, codec_context->height, codec_context->pix_fmt, kVideoWidth, kVideoHeight, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
    SDL_Window* window = SDL_CreateWindow("Video Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, kVideoWidth, kVideoHeight, SDL_WINDOW_OPENGL);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, kVideoWidth, kVideoHeight);
    AVPacket packet;
    AVFormatContext* output_format_context = nullptr;
    if (avformat_alloc_output_context2(&output_format_context, nullptr, nullptr, kOutputPath.c_str()) < 0)
    {
        std::cerr << "Failed to allocate output format context" << std::endl;
        return -1;
    }
    AVStream* output_stream = avformat_new_stream(output_format_context, codec);
    if (output_stream == nullptr)
    {
        std::cerr << "Failed to allocate output stream" << std::endl;
        return -1;
    }
    if (avcodec_parameters_copy(output_stream->codecpar, format_context->streams[stream_index]->codecpar) < 0)
    {
        std::cerr << "Failed to copy codec parameters to output stream" << std::endl;
        return -1;
    }
    output_stream->time_base = format_context->streams[stream_index]->time_base;
    if (!(output_format_context->oformat->flags & AVFMT_NOFILE))
    {
        if (avio_open(&output_format_context->pb, kOutputPath.c_str(), AVIO_FLAG_WRITE) < 0)
        {
            std::cerr << "Failed to open output file" << std::endl;
            return -1;
        }
    }
    if (avformat_write_header(output_format_context, nullptr) < 0)
    {
        std::cerr << "Failed to write output file header" << std::endl;
        return -1;
    }
    bool is_running = true;
    int64_t start_pts = kStartTime * AV_TIME_BASE;
    int64_t end_pts = kEndTime * AV_TIME_BASE;
    while (av_read_frame(format_context, &packet) >= 0 && is_running)
    {
        if (packet.stream_index == stream_index)
        {
            if (avcodec_send_packet(codec_context, &packet) == 0)
            {
                while (avcodec_receive_frame(codec_context, frame) == 0)
                {
                    if (frame->pts >= start_pts && frame->pts <= end_pts)
                    {
                        sws_scale(sws_context, frame->data, frame->linesize, 0, codec_context->height, frame_rgb->data, frame_rgb->linesize);
                        SDL_UpdateTexture(texture, nullptr, frame_rgb->data[0], frame_rgb->linesize[0]);
                        SDL_RenderClear(renderer);
                        SDL_RenderCopy(renderer, texture, nullptr, nullptr);
                        SDL_RenderPresent(renderer);
                        if (av_write_frame(output_format_context, &packet) < 0)
                        {
                            std::cerr << "Failed to write frame to output file" << std::endl;
                            return -1;
                        }
                        if (av_gettime_relative() >= end_pts)
                        {
                            is_running = false;
                            break;
                        }
                    }
                }
            }
        }
        av_packet_unref(&packet);
    }
    av_write_trailer(output_format_context);
    av_frame_free(&frame);
    av_frame_free(&frame_rgb);
    avcodec_close(codec_context);
    avformat_close_input(&format_context);
    avformat_free_context(format_context);
    av_free(buffer);
    avio_close(output_format_context->pb);
    avformat_free_context(output_format_context);
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}



图片附件: 游客没有浏览图片的权限,请 登录注册

图片附件: 游客没有浏览图片的权限,请 登录注册

图片附件: 游客没有浏览图片的权限,请 登录注册


剪辑10秒钟视频 大小才1K。。。。
播放器 没有音频  2分4.86秒的视频。 50秒就播放完成了。。。。


你是不是要告诉我,代码如果拿到手,就可以正常使用,我就什么知识点也学不到了。。。。
写出了程序流程,让我自己找错误,这样才能更好地学习。。。。
2023-04-12 21:06
追梦人zmrghy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:406
专家分:190
注 册:2021-4-9
收藏
得分:0 
回复 4楼 东海ECS
图片附件: 游客没有浏览图片的权限,请 登录注册


什么也没有,就是一个空文件。。。



图片附件: 游客没有浏览图片的权限,请 登录注册


fram->pts最大4280320
start_pts = 5000000


图片附件: 游客没有浏览图片的权限,请 登录注册


fram->pts每次增加640




图片附件: 游客没有浏览图片的权限,请 登录注册


4280320÷640÷25÷60=视频时间长度。。。




图片附件: 游客没有浏览图片的权限,请 登录注册


视频文件,有了5秒时长。
1kbps 每一帧,都是空和吧,
没有写入视频数据。。。。。
2023-04-14 02:33
快速回复:求助:VS2022和FFmpeg如何开发出视频剪辑软件。。。
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.025458 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved