基于C语言生成一个FFMPEG输出音频文件的代码
时间: 2024-05-01 11:23:31 浏览: 139
以下是一个基于FFmpeg库生成音频文件的简单示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <libavutil/channel_layout.h>
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#define OUTPUT_FORMAT "wav"
#define SAMPLE_RATE 44100
#define BIT_RATE 64000
#define CHANNEL_LAYOUT AV_CH_LAYOUT_STEREO
#define SAMPLE_FORMAT AV_SAMPLE_FMT_S16
#define DURATION 5.0 // 5 seconds
#define AMPLITUDE 20000.0 // signal amplitude
#define PI 3.14159265358979323846
int main(int argc, char *argv[]) {
AVFormatContext *format_ctx = NULL;
AVOutputFormat *output_format = NULL;
AVCodec *codec = NULL;
AVStream *stream = NULL;
AVCodecContext *codec_ctx = NULL;
AVFrame *frame = NULL;
AVPacket pkt;
SwrContext *resample_ctx = NULL;
int ret, i, j, buffer_size, nb_samples;
uint8_t **converted_samples = NULL;
int64_t pts = 0;
// Open output file context
avformat_alloc_output_context2(&format_ctx, NULL, OUTPUT_FORMAT, NULL);
if (!format_ctx) {
fprintf(stderr, "Error allocating output context\n");
return 1;
}
output_format = format_ctx->oformat;
// Open output file
if (!(output_format->flags & AVFMT_NOFILE)) {
ret = avio_open(&format_ctx->pb, "output.wav", AVIO_FLAG_WRITE);
if (ret < 0) {
fprintf(stderr, "Error opening output file\n");
return 1;
}
}
// Add audio stream
codec = avcodec_find_encoder(output_format->audio_codec);
if (!codec) {
fprintf(stderr, "Error finding audio codec\n");
return 1;
}
stream = avformat_new_stream(format_ctx, codec);
if (!stream) {
fprintf(stderr, "Error creating new audio stream\n");
return 1;
}
codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) {
fprintf(stderr, "Error allocating audio codec context\n");
return 1;
}
codec_ctx->sample_fmt = SAMPLE_FORMAT;
codec_ctx->sample_rate = SAMPLE_RATE;
codec_ctx->channel_layout = CHANNEL_LAYOUT;
codec_ctx->bit_rate = BIT_RATE;
if (format_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
ret = avcodec_open2(codec_ctx, codec, NULL);
if (ret < 0) {
fprintf(stderr, "Error opening audio codec\n");
return 1;
}
ret = avcodec_parameters_from_context(stream->codecpar, codec_ctx);
if (ret < 0) {
fprintf(stderr, "Error initializing stream parameters\n");
return 1;
}
stream->time_base = (AVRational){1, codec_ctx->sample_rate};
// Create audio frame
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Error allocating audio frame\n");
return 1;
}
frame->format = codec_ctx->sample_fmt;
frame->channel_layout = codec_ctx->channel_layout;
frame->sample_rate = codec_ctx->sample_rate;
frame->nb_samples = codec_ctx->frame_size;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
fprintf(stderr, "Error allocating audio frame samples\n");
return 1;
}
// Initialize resampler
resample_ctx = swr_alloc_set_opts(NULL, codec_ctx->channel_layout, codec_ctx->sample_fmt, codec_ctx->sample_rate,
av_get_default_channel_layout(2), AV_SAMPLE_FMT_FLT, SAMPLE_RATE, 0, NULL);
if (!resample_ctx) {
fprintf(stderr, "Error allocating resampler context\n");
return 1;
}
ret = swr_init(resample_ctx);
if (ret < 0) {
fprintf(stderr, "Error initializing resampler context\n");
return 1;
}
// Generate audio samples and encode frames
nb_samples = codec_ctx->frame_size;
buffer_size = av_samples_get_buffer_size(NULL, 2, nb_samples, AV_SAMPLE_FMT_FLT, 0);
converted_samples = (uint8_t **)calloc(2, sizeof(uint8_t *));
converted_samples[0] = (uint8_t *)calloc(buffer_size, sizeof(uint8_t));
converted_samples[1] = (uint8_t *)calloc(buffer_size, sizeof(uint8_t));
for (i = 0; i < DURATION * SAMPLE_RATE; i += nb_samples) {
// Generate sine wave samples
for (j = 0; j < nb_samples; j++) {
float t = (float)pts / (float)SAMPLE_RATE;
float sample = AMPLITUDE * sin(2 * PI * 440 * t);
((float *)converted_samples[0])[j] = sample;
((float *)converted_samples[1])[j] = sample;
pts++;
}
// Resample and encode frame
ret = swr_convert(resample_ctx, converted_samples, nb_samples, (const uint8_t **)frame->extended_data, nb_samples);
if (ret < 0) {
fprintf(stderr, "Error resampling samples\n");
return 1;
}
frame->pts = av_rescale_q(i, stream->time_base, (AVRational){1, SAMPLE_RATE});
ret = avcodec_send_frame(codec_ctx, frame);
if (ret < 0) {
fprintf(stderr, "Error sending audio frame for encoding\n");
return 1;
}
while (ret >= 0) {
ret = avcodec_receive_packet(codec_ctx, &pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
}
if (ret < 0) {
fprintf(stderr, "Error during audio encoding\n");
return 1;
}
pkt.stream_index = stream->index;
av_packet_rescale_ts(&pkt, codec_ctx->time_base, stream->time_base);
ret = av_interleaved_write_frame(format_ctx, &pkt);
av_packet_unref(&pkt);
if (ret < 0) {
fprintf(stderr, "Error writing audio frame\n");
return 1;
}
}
}
// Finalize output file
av_write_trailer(format_ctx);
// Cleanup resources
avcodec_free_context(&codec_ctx);
av_frame_free(&frame);
avformat_close_input(&format_ctx);
avformat_free_context(format_ctx);
swr_free(&resample_ctx);
free(converted_samples[0]);
free(converted_samples[1]);
free(converted_samples);
return 0;
}
```
该示例使用了FFmpeg的库来生成一个5秒钟的440Hz正弦波音频文件。它使用了一个PCM音频流,采样率为44100Hz,双声道,每个样本为16位有符号整数。输出格式为WAV。
在编译前,需要确保FFmpeg库已经被正确地安装和配置。编译命令如下:
```
gcc -o output audio_generator.c -lavformat -lavcodec -lavutil -lswresample
```
其中,`-lavformat`、`-lavcodec`、`-lavutil`和`-lswresample`是链接FFmpeg库的选项。
阅读全文