gstreamer flacenc如何向flac文件添加持续时间信息?

gstreamer flacenc如何向flac文件添加持续时间信息?,gstreamer,record,flac,Gstreamer,Record,Flac,我正在使用gstreamer(gst-launch-1.0版本1.8.3)记录flac文件。命令行如下所示: gst-launch-1.0 -v alsasrc ! flacenc ! filesink location="output.flac" mediainfo output.flac 上图显示了使用mediainfo的结果 此文件可以在media player上播放,但不支持导航和播放时间。 我认为没有持续时间信息 如何将持续时间信息添加到flac文件中?我认为.flac是一种非常

我正在使用gstreamer(gst-launch-1.0版本1.8.3)记录flac文件。命令行如下所示:

gst-launch-1.0 -v alsasrc ! flacenc ! filesink location="output.flac"
mediainfo output.flac

上图显示了使用mediainfo的结果

此文件可以在media player上播放,但不支持导航和播放时间。 我认为没有持续时间信息


如何将持续时间信息添加到flac文件中?

我认为.flac是一种非常基本的流格式。它不支持随机访问或带有持续时间。除非解析完整的文件,否则无法知道确切的持续时间。有些玩家可能会在这里采取“尽最大努力”的方法,试图大致确定文件的位置,直到你将滑块滑出的位置,但格式本身并没有提供任何东西

我想为了寻找你应该把.flac放进一个像.ogg这样的容器里。这实际上非常类似于.aac文件,它应该放在.mp4中

所以试试
gst-launch-1.0-e-v alsasrc!弗拉森克!oggmux!filesink location=“output.ogg”


我对user199309的答案做了一些修改

编译:g++-o test.c$(pkg-config--cflags--libs-gstreamer-1.0)

#包括
#包括
#定义GLIB\u禁用\u弃用\u警告
静态GstElement*管道;
静态GstPad*队列_src _pad;
静态GstElement*存储箱[2];
静态GstPad*bin_焊盘[2];
静态GstElement*文件链接[2];
静态GMainLoop*循环;
静态GstElement*flacenc[2];
静态大小\u t当前\u bin=0;
静态int当前_文件=0;
静态GSTPADProbe返回
pad_probe_cb(GstPad*pad、GstPadProbeInfo*信息、gpointer用户_数据){
gst_焊盘_移除_探头(焊盘,gst_焊盘_探头_信息_ID(信息));
gst_pad_unlink(队列_src_pad,bin_pad[当前_bin]);
gst_pad_send_事件(bin_pad[当前_bin],gst_事件_new_eos());
gst\u元素\u集合\u状态(bins[当前\u bin],gst\u状态\u NULL);
gst_对象_参考(仓位[当前仓位]);
gst_-bin_移除(gst_-bin(管道)、料仓[当前料仓]);
当前_文件++;
当前\u bin=(当前\u文件%2);
{
字符文件_位置[32];
sprintf(文件位置,“录制%ld.flac”,当前文件);
g_对象集(g_对象(
文件链接[当前位置],“位置”,文件位置,空);
printf(“正在写入%s\n”,文件位置);
}
gst_bin_add(gst_bin(管道),bin[当前_bin]);
gst_pad_链接(队列_src_pad,bin_pad[当前_bin]);
gst元素设置状态(箱子[当前箱子],gst状态播放);
gst元素与父项同步状态(bin[当前bin]);
返回GST\u焊盘\u探头\u正常;
}
静态gboolean超时\u cb(gpointer用户\u数据){
gst\U焊盘\U添加\U探头(队列\U src\U焊盘、gst\U焊盘\U探头\U类型\U块\U下游、,
pad_探头_cb,空,空);
返回TRUE;
}
静态gboolean
总线断路器(GstBus*总线,
GstMessage*msg,
gpointer数据)
{
GMainLoop*循环=(GMainLoop*)数据;
g_打印(“获取%s消息\n”,GST_消息类型_名称(msg));
开关(GST\信息\类型(msg)){
案例GST\信息\ EOS:
g_打印(“流结束\n”);
//g_主循环退出(循环);
打破
案例GST\u消息\u错误:{
gchar*调试;
GError*错误;
gst\消息\解析\错误(消息、错误和调试);
g_自由(调试);
g_printerr(“错误:%s\n”,错误->消息);
g_无错误(错误);
g_主循环退出(循环);
打破
}
违约:
打破
}
返回TRUE;
}
gint干管(gint-argc,gchar*argv[])
{
GstElement*audiosrc;
GstElement*队列;
GstBus*总线;
GMainLoop*循环;
pthread_t libusb_tid;
吉尼特巴士公司;
gst_init(&argc,&argv);
audiosrc=gst元素工厂制造(“ALASRC”、“audiosrc”);
队列=gst元素工厂制造(“队列”、“队列”);
bins[0]=gst_bin_new(“bin0”);
bins[1]=gst_bin_new(“bin1”);
flacenc[0]=商品及服务税(gst)、要素、工厂制造(“flacenc”、“flacenc0”);
flacenc[1]=商品及服务税要素工厂制造(“flacenc”、“flacenc1”);
filesink[0]=gst元素工厂制造(“filesink”、“filesink0”);
filesink[1]=gst元素工厂制造(“filesink”、“filesink1”);
管道=gst_管道_新(“测试管道”);
如果(!pipeline | | |!audiosrc | |!队列
||!flacenc[0]| |!filesink[0]
||!flacenc[1]| |!filesink[1]
) {
g_printerr(“不是所有元素都可以创建\n”);
//返回-1;
}
gst_bin_add_many(gst_bin(bin[0]),flacenc[0],filesink[0],NULL);
gst_-bin_-add_-many(gst_-bin(bin[1]),flacenc[1],filesink[1],NULL);
gst_bin_add_many(gst_bin(管道)、audiosrc、queue、bin[0],NULL);
g_断言(gst_元素链接(audiosrc,queue));
g_assert(gst_元素_链接_许多(flacenc[0],filesink[0],NULL));
g_assert(gst_元素_链接_许多(flacenc[1],filesink[1],NULL));
GstPad*pad=gst_元素_get_静态_pad(flacenc[0],“sink”);
gst_元件_添加_焊盘(箱[0],gst_鬼焊盘_新(“水槽”,焊盘));
商品及服务税(pad);
GstPad*pad2=gst_元件_获取_静态_垫(flacenc[1],“接收器”);
gst_元件添加焊盘(箱[1],gst_鬼焊盘新(“水槽”,焊盘2));
商品及服务税(pad2);
bin_焊盘[0]=gst_元件_获取_静态_焊盘(bin[0],“水槽”);
垃圾桶垫[1]=垃圾桶垫(垃圾桶[1],“水槽”);
当前_bin=0;
gst_元素_链接(队列、箱[当前箱]);
g_对象_集(filesink[current_bin],“location”,“recording_0.flac”,NULL);
queue_src_pad=gst_element_get_static_pad(队列,“src”);
总线=gst\u元件\u获取\u总线(管道);
总线\监视\ id=gst\总线\添加\监视(总线、总线\ cb、环路);
gst元素设置状态(管道、gst状态);
loop=g_main_loop_new(NULL,FALSE);
g\u超时\u添加\u秒(10,超时\u cb,空);
g_主循环运行(循环);
商品及服务税(巴士);
gst\元素\集合\状态(管道,gst\状态\空);
gst_对象_unref(管道);
返回0;
}

谢谢您的回答。使用ffmpeg录制时,存在持续时间字段。命令:ffmpeg-falsa-ac1-ar44100-ihw:1,0output.flacSo可能有一个非正式的met
$ mediainfo output.ogg 
General
Complete name                            : output.ogg
Format                                   : Ogg
Format/Info                              : Free Lossless Audio Codec
File size                                : 598 KiB
Duration                                 : 7 s 941 ms
Overall bit rate mode                    : Variable
Overall bit rate                         : 617 kb/s

Audio
ID                                       : 256729656 (0xF4D6238)
Format                                   : FLAC
Format/Info                              : Free Lossless Audio Codec
Duration                                 : 7 s 941 ms
Bit rate mode                            : Variable
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Sampling rate                            : 44.1 kHz
Bit depth                                : 16 bits
Writing library                          : libFLAC 1.3.2 (UTC 2017-01-01)
#include <stdio.h>
#include <gst/gst.h>

#define GLIB_DISABLE_DEPRECATION_WARNINGS

static GstElement *pipeline;
static GstPad *queue_src_pad;
static GstElement *bins[2];
static GstPad *bin_pads[2];
static GstElement *filesink[2];
static GMainLoop *loop;
static GstElement *flacenc[2];
static size_t current_bin = 0;
static int current_file = 0;

static GstPadProbeReturn
    pad_probe_cb(GstPad * pad, GstPadProbeInfo * info, gpointer user_data) {
    gst_pad_remove_probe(pad, GST_PAD_PROBE_INFO_ID (info));

    gst_pad_unlink(queue_src_pad, bin_pads[current_bin]);
    gst_pad_send_event(bin_pads[current_bin], gst_event_new_eos());
    gst_element_set_state(bins[current_bin], GST_STATE_NULL);
    gst_object_ref(bins[current_bin]);
    gst_bin_remove(GST_BIN(pipeline), bins[current_bin]);


    current_file++;
    current_bin = (current_file % 2);

    {
    char file_location[32];
    sprintf(file_location, "recording_%ld.flac", current_file);
    g_object_set(G_OBJECT(
            filesink[current_bin]), "location", file_location, NULL);

    printf("now writing to %s\n", file_location);
    }

    gst_bin_add(GST_BIN(pipeline), bins[current_bin]);
    gst_pad_link(queue_src_pad, bin_pads[current_bin]);
    gst_element_set_state(bins[current_bin], GST_STATE_PLAYING);
    gst_element_sync_state_with_parent(bins[current_bin]);

    return GST_PAD_PROBE_OK;
}

static gboolean timeout_cb(gpointer user_data) {
    gst_pad_add_probe(queue_src_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
        pad_probe_cb, NULL, NULL);

    return TRUE;
}

static gboolean
bus_cb (GstBus     *bus,
        GstMessage *msg,
        gpointer    data)
{
    GMainLoop *loop = (GMainLoop *)data;
    g_print("Got %s message\n", GST_MESSAGE_TYPE_NAME(msg));
    switch (GST_MESSAGE_TYPE (msg)) {

    case GST_MESSAGE_EOS:
        g_print ("End of stream\n");
        //g_main_loop_quit (loop);
        break;

    case GST_MESSAGE_ERROR: {
        gchar  *debug;
        GError *error;

        gst_message_parse_error(msg, &error, &debug);
        g_free(debug);

        g_printerr("Error: %s\n", error->message);
        g_error_free(error);

        g_main_loop_quit(loop);
        break;
    }
    default:
        break;
    }

    return TRUE;
}

gint main(gint argc, gchar *argv[])
{
    GstElement *audiosrc;
    GstElement *queue;
    GstBus *bus;
    GMainLoop *loop;
    pthread_t libusb_tid;
    guint bus_watch_id;

    gst_init (&argc, &argv);

    audiosrc = gst_element_factory_make("alsasrc", "audiosrc");

    queue = gst_element_factory_make("queue", "queue");

    bins[0] = gst_bin_new("bin0");
    bins[1] = gst_bin_new("bin1");

    flacenc[0] = gst_element_factory_make("flacenc", "flacenc0");
    flacenc[1] = gst_element_factory_make("flacenc", "flacenc1");

    filesink[0] = gst_element_factory_make("filesink", "filesink0");
    filesink[1] = gst_element_factory_make("filesink", "filesink1");

    pipeline = gst_pipeline_new("test-pipeline");

    if (!pipeline || !audiosrc || !queue
            || !flacenc[0] || !filesink[0]
            || !flacenc[1] || !filesink[1]
            ) {
        g_printerr ("not all elements could be created\n");
        //return -1;
    }
    gst_bin_add_many(GST_BIN(bins[0]), flacenc[0], filesink[0], NULL);
    gst_bin_add_many(GST_BIN(bins[1]), flacenc[1], filesink[1], NULL);
    gst_bin_add_many(GST_BIN(pipeline), audiosrc, queue, bins[0], NULL);

    g_assert(gst_element_link(audiosrc, queue));

    g_assert(gst_element_link_many(flacenc[0], filesink[0], NULL));
    g_assert(gst_element_link_many(flacenc[1], filesink[1], NULL));

    GstPad* pad = gst_element_get_static_pad(flacenc[0], "sink");
    gst_element_add_pad(bins[0], gst_ghost_pad_new("sink", pad));
    gst_object_unref(pad);

    GstPad* pad2 = gst_element_get_static_pad(flacenc[1], "sink");
    gst_element_add_pad(bins[1], gst_ghost_pad_new("sink", pad2));
    gst_object_unref(pad2);

    bin_pads[0] = gst_element_get_static_pad(bins[0], "sink");
    bin_pads[1] = gst_element_get_static_pad(bins[1], "sink");

    current_bin = 0;
    gst_element_link(queue, bins[current_bin]);
    g_object_set(filesink[current_bin], "location", "recording_0.flac", NULL);

    queue_src_pad = gst_element_get_static_pad(queue, "src");

    bus = gst_element_get_bus(pipeline);
    bus_watch_id = gst_bus_add_watch(bus, bus_cb, loop);

    gst_element_set_state(pipeline, GST_STATE_PLAYING);

    loop = g_main_loop_new(NULL, FALSE);
    g_timeout_add_seconds(10, timeout_cb, NULL);
    g_main_loop_run (loop);

    gst_object_unref(bus);
    gst_element_set_state(pipeline, GST_STATE_NULL);

    gst_object_unref(pipeline);
    return 0;
}