ffmpeg精确截取视频片段
时间: 2023-10-05 11:07:40 浏览: 62
使用ffmpeg可以通过指定起始时间和时长来精确截取视频片段。下面是一些常见的命令行示例:
1. 截取从视频开头开始的前30秒:
```
ffmpeg -i input.mp4 -t 30 output.mp4
```
2. 截取从视频第10秒开始的30秒:
```
ffmpeg -i input.mp4 -ss 00:00:10 -t 30 output.mp4
```
3. 截取从视频第10秒开始到结束:
```
ffmpeg -i input.mp4 -ss 00:00:10 -to end output.mp4
```
4. 截取从视频第10秒开始到第20秒:
```
ffmpeg -i input.mp4 -ss 00:00:10 -t 00:00:10 output.mp4
```
注意,以上命令行示例中的时间格式为“时:分:秒”,也可以使用“秒”的形式表示时间,例如“-ss 10”表示从视频第10秒开始截取。
相关问题
ffmpeg截取视频片段
可以使用 ffmpeg 的命令行工具来截取视频片段。以下是一个示例命令,假设要截取从视频的第 10 秒开始,持续 5 秒钟的片段:
```
ffmpeg -i input.mp4 -ss 00:00:10 -t 00:00:05 -c copy output.mp4
```
其中,`-i` 参数指定输入文件名,`-ss` 参数指定开始时间,`-t` 参数指定持续时间,`-c copy` 参数表示直接复制视频和音频流,以加快处理速度。最后一个参数是输出文件名。
如果需要截取多个片段,可以多次执行上述命令,每次指定不同的开始时间和持续时间。
FFmpeg c++ 如何截取视频片段
在 C++ 中使用 FFmpeg 截取视频片段,可以按照以下步骤进行:
1. 引入 FFmpeg 头文件
```c++
extern "C" {
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}
```
2. 打开视频文件
```c++
AVFormatContext *pFormatCtx = nullptr;
if (avformat_open_input(&pFormatCtx, filename, nullptr, nullptr) < 0) {
// 打开文件失败
return;
}
if (avformat_find_stream_info(pFormatCtx, nullptr) < 0) {
// 获取文件信息失败
return;
}
```
3. 查找视频流
```c++
int videoStream = -1;
for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
break;
}
}
if (videoStream == -1) {
// 没有找到视频流
return;
}
```
4. 获取视频编解码器
```c++
AVCodecParameters *pCodecParams = pFormatCtx->streams[videoStream]->codecpar;
AVCodec *pCodec = avcodec_find_decoder(pCodecParams->codec_id);
if (pCodec == nullptr) {
// 没有找到对应的编解码器
return;
}
AVCodecContext *pCodecCtx = avcodec_alloc_context3(pCodec);
if (pCodecCtx == nullptr) {
// 分配编解码器上下文失败
return;
}
if (avcodec_parameters_to_context(pCodecCtx, pCodecParams) < 0) {
// 设置编解码器上下文参数失败
return;
}
if (avcodec_open2(pCodecCtx, pCodec, nullptr) < 0) {
// 打开编解码器失败
return;
}
```
5. 创建解码器帧和转换器
```c++
AVFrame *pFrame = av_frame_alloc();
if (pFrame == nullptr) {
// 分配解码器帧失败
return;
}
AVFrame *pFrameRGB = av_frame_alloc();
if (pFrameRGB == nullptr) {
// 分配转换器帧失败
return;
}
int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
uint8_t *buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
if (buffer == nullptr) {
// 分配转换器缓冲区失败
return;
}
av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
struct SwsContext *swsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
if (swsCtx == nullptr) {
// 创建转换器失败
return;
}
```
6. 定位到开始截取的位置
```c++
int64_t startTimestamp = startTimeInSeconds * AV_TIME_BASE;
if (av_seek_frame(pFormatCtx, videoStream, startTimestamp, AVSEEK_FLAG_BACKWARD) < 0) {
// 定位到指定时间戳失败
return;
}
```
7. 读取视频帧并进行截取
```c++
int gotFrame = 0;
AVPacket packet;
while (av_read_frame(pFormatCtx, &packet) >= 0) {
if (packet.stream_index == videoStream) {
avcodec_decode_video2(pCodecCtx, pFrame, &gotFrame, &packet);
if (gotFrame) {
int64_t pts = av_frame_get_best_effort_timestamp(pFrame);
if (pts >= endTimestamp) {
break;
}
sws_scale(swsCtx, (uint8_t const *const *) pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
// 处理截取后的视频帧
}
}
av_packet_unref(&packet);
}
```
8. 释放资源
```c++
sws_freeContext(swsCtx);
av_frame_free(&pFrameRGB);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
```
其中,`startTimeInSeconds` 和 `endTimeInSeconds` 分别为要截取的视频片段的开始时间和结束时间,以秒为单位。`AV_TIME_BASE` 定义了时间戳的时间基,一般为 1 秒钟的微秒数(1000000)。`AVSEEK_FLAG_BACKWARD` 表示定位到离指定时间戳最近的关键帧之前的位置。