使用 ffmpeg 添加元数据信息
Adding metadata informations with ffmpeg
我正在尝试读取,最重要的是使用 ffmpeg 将元数据写入文件。但是我正在得到sigseg。
int main(int argc, char **argv) {
av_register_all();
AVFormatContext* ctx;
std::string path("/home/stefan/test_track.mp3");
ctx = avformat_alloc_context();
if (avformat_open_input(&ctx, path.c_str(), 0, 0) < 0)
std::cout << "error1" << std::endl;
if (avformat_find_stream_info(ctx, 0) < 0)
std::cout << "error2" << std::endl;
AVDictionaryEntry *tag = nullptr;
tag = av_dict_get(ctx->metadata, "artist", tag, AV_DICT_IGNORE_SUFFIX);
std::cout << tag->key << " : " << tag->value << std::endl;
av_dict_set(&ctx->metadata, "TPFL", "testtest", 0);
std::cout << "test!" << std::endl;
int status = avformat_write_header(ctx, &ctx->metadata);
if(status == 0)
std::cout << "test1" << std::endl;
return 0;
}
我还尝试制作AVDictionary的完整副本,而不是使用新添加的要保存的字段来保存它。但仍然会感到不安。
我错过了什么?
您需要使用另一个AVFormatContext
来编写输出。
在您的示例中,只需添加一些元数据并复制编解码器,因此 ffmpeg 库的复用步骤是
- 创建所需的输出格式上下文,
avformat_alloc_output_context2
- 将流添加到输出格式上下文,
avformat_new_stream
- 添加一些自定义元数据和写入标头
- 使用
av_write_frame
写入编码数据 - 写预告片
下面是一个可行的示例,对代码进行了少量修改。
#include <iostream>
#ifdef __cplusplus
extern "C" {
#endif
#include <libavformat/avformat.h>
#ifdef __cplusplus
}
#endif
int main(int argc, char **argv) {
av_register_all();
avcodec_register_all();
AVFormatContext* ctx;
std::string path("./input.mp3");
ctx = avformat_alloc_context();
if (avformat_open_input(&ctx, path.c_str(), 0, 0) < 0)
std::cout << "error1" << std::endl;
if (avformat_find_stream_info(ctx, 0) < 0)
std::cout << "error2" << std::endl;
AVDictionaryEntry *tag = nullptr;
tag = av_dict_get(ctx->metadata, "artist", tag, AV_DICT_IGNORE_SUFFIX);
std::cout << tag->key << " : " << tag->value << std::endl;
av_dict_set(&ctx->metadata, "TPFL", "testtest", 0);
std::cout << "test!" << std::endl;
int status;
AVFormatContext* ofmt_ctx;
AVOutputFormat* ofmt = av_guess_format("mp3", "./out.mp3", NULL);
status = avformat_alloc_output_context2(&ofmt_ctx, ofmt, "mp3", "./out.mp3");
if (status < 0) {
std::cerr << "could not allocate output format" << std::endl;
return 0;
}
int audio_stream_index = 0;
for (unsigned i = 0; i < ctx->nb_streams; i++) {
if (ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audio_stream_index = i;
const AVCodec *c = avcodec_find_encoder(ctx->streams[i]->codecpar->codec_id);
if (c) {
AVStream *ostream = avformat_new_stream(ofmt_ctx, c);
avcodec_parameters_copy(ostream->codecpar, ctx->streams[i]->codecpar);
ostream->codecpar->codec_tag = 0;
}
break;
}
}
av_dict_set(&ofmt_ctx->metadata, "TPFL", "testtest", 0);
av_dump_format(ofmt_ctx, 0, "./out.mp3", 1);
if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) {
avio_open(&ofmt_ctx->pb, "./out.mp3", AVIO_FLAG_WRITE);
}
if (avformat_init_output(ofmt_ctx, NULL) == AVSTREAM_INIT_IN_WRITE_HEADER) {
status = avformat_write_header(ofmt_ctx, NULL);
}
AVPacket *pkt = av_packet_alloc();
av_init_packet(pkt);
pkt->data = NULL;
pkt->size = 0;
while (av_read_frame(ctx, pkt) == 0) {
if (pkt->stream_index == audio_stream_index) {
// this is optional, we are copying the stream
av_packet_rescale_ts(pkt, ctx->streams[audio_stream_index]->time_base,
ofmt_ctx->streams[audio_stream_index]->time_base);
av_write_frame(ofmt_ctx, pkt);
}
}
av_packet_free(&pkt);
av_write_trailer(ofmt_ctx);
avformat_close_input(&ctx);
avformat_free_context(ofmt_ctx);
avformat_free_context(ctx);
if(status == 0)
std::cout << "test1" << std::endl;
return 0;
}
完成后,您可以使用ffprobe output.mp3
检查写入的元数据。
Input #0, mp3, from 'out.mp3':
Metadata:
TPFL : testtest
encoder : Lavf57.75.100
Duration: 00:00:08.75, start: 0.011995, bitrate: 128 kb/s
Stream #0:0: Audio: mp3, 44100 Hz, stereo, s16p, 128 kb/s
Metadata:
encoder : Lavf
相关文章:
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 以非特权用户身份查询 NTFS 特殊文件的元数据?
- 如何使用 Google Test 向测试添加元数据 / 如何将数据从 Google Test 发送到 TestEven
- 将复杂的非基元C++数据类型转换为 Erlang/Elixir 格式,以使用 NIF 导出方法
- 从模板创建通用打印函数,以打印基元数据类型变量的值
- 在 C++ 中修改 Grpc 双向流式处理期间的元数据
- cpp / c ++中的grpc客户端代码,元数据x-api-key/x-goog-api-key不起作用,给了我语音A
- 学生信息的数据绑定
- 如何使用gRPC在客户端和服务器之间双向发送和接收流元数据
- 即使基类和派生类只使用基元数据类型,我是否需要定义虚拟析构函数
- 如何处理错误"E1696命令行错误:无法在Visual Studio 2017中打开元数据文件"mscorlib.dll"?
- 元数据操作失败LNK2022错误 (8013118D):重复类型中的布局信息不一致 (选择设备参数):(0x020002
- C++11 标准中的哪一部分规定了基元数据类型大小之间的相对顺序?
- 使用 ffmpeg 添加元数据信息
- WIC - Exif 元数据查询 - 如何获取图像说明
- 从Qt应用程序读取元数据
- 如何将编译时元数据/行为添加到特定函数
- 从编码域中的 MPEG 文件中读取元数据
- 在C 中显示图像及其元数据
- C :源代码中的元数据信息.查看AST