如何在 C 程序中使用 Gstreamer 在视频中动态添加和删除字幕

Posted

技术标签:

【中文标题】如何在 C 程序中使用 Gstreamer 在视频中动态添加和删除字幕【英文标题】:How to add and remove dynamically subtitle in video with Gstreamer in a C program 【发布时间】:2014-10-29 10:07:31 【问题描述】:

对于一个学校项目,我必须用 gstreamer 和 gtk 做一个视频阅读器,没有 playbin2。 在这个阅读器中,我必须在阅读视频时添加和删除字幕。

目前我使用decodebin 播放所有格式但无法添加字幕。 我成功地使用 oggdemux 获得了动态字幕,但此解决方案仅适用于 ogg 格式。所以,我用 decodebin 搜索其他解决方案。

我尝试了很多解决方案:

解码箱和字幕

首先,我尝试将字幕 gstreamer 元素直接添加到视频队列中。我确切地说我的程序在没有字幕 gstreamer 元素的情况下工作(正在播放音频/视频)。

// Creation of many elements of gstreamer
data.pipeline = gst_pipeline_new ("video-player");  
source_media = gst_element_factory_make ("filesrc",     "file-source");    
demuxer  = gst_element_factory_make ("decodebin",   "decodebin");
// AUDIO -----
sink_audio = gst_element_factory_make ("autoaudiosink", "audio-output");
queue_audio = gst_element_factory_make("queue", "thread-audio");

// VIDEO -----
sink_video  = gst_element_factory_make ("autovideosink", "video-output");    
queue_video = gst_element_factory_make("queue", "thread-video");

// SUBTITLE -----    
source_sub = gst_element_factory_make("filesrc", "sub-source");
subparse = gst_element_factory_make("subparse", "subparse");
textoverlay = gst_element_factory_make ("subtitleoverlay", "subtitleoverlay");

g_object_set (G_OBJECT (source_media), "location", argv[1], NULL);

gst_bin_add_many (GST_BIN (data.pipeline),
                     source_media, demuxer,
                     queue_audio, sink_audio,  
                     queue_video, sink_video,
                     source_sub, subparse, textoverlay, 
                     NULL);

gst_element_link (source_media, demuxer);            
gst_element_link_many (queue_audio, sink_audio, NULL);
g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), queue_audio);
gst_element_link_many (queue_video, textoverlay, sink_video, NULL);
g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), queue_video);    
gst_element_link_many (source_sub, subparse, textoverlay, NULL);

新的字幕管道

其次,我尝试创建另一个仅包含字幕 gstreamer 元素的管道

// Creation of many elements of gstreamer
data.pipeline = gst_pipeline_new ("video-player");  
date.subtitle = gst_pipeline_new ("subtitles");
source_media = gst_element_factory_make ("filesrc",     "file-source");    
demuxer  = gst_element_factory_make ("decodebin",   "decodebin");
// AUDIO -----
sink_audio = gst_element_factory_make ("autoaudiosink", "audio-output");
queue_audio = gst_element_factory_make("queue", "thread-audio");

// VIDEO -----
sink_video  = gst_element_factory_make ("autovideosink", "video-output");    
queue_video = gst_element_factory_make("queue", "thread-video");

// SUBTITLE -----    
source_sub = gst_element_factory_make("filesrc", "sub-source");
subparse = gst_element_factory_make("subparse", "subparse");
textoverlay = gst_element_factory_make ("subtitleoverlay", "subtitleoverlay");

g_object_set (G_OBJECT (source_media), "location", argv[1], NULL);
g_object_set (G_OBJECT (source_sub), "location", argv[2], NULL);

gst_bin_add_many (GST_BIN (data.pipeline),
                     source_media, demuxer,
                     queue_audio, sink_audio,  
                     queue_video, sink_video, NULL);

gst_bin_add_many(GST_BIN (data.subtitle),
                 source_sub, subparse, textoverlay,
                 NULL);

gst_element_link (source_media, demuxer);  
gst_element_link (source_sub, subparse);

gst_element_link_many (queue_audio, sink_audio, NULL);
g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), queue_audio);
gst_element_link_many (queue_video, textoverlay, sink_video, NULL);
g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), queue_video);    
gst_element_link_many (source_sub, subparse, textoverlay, NULL);

if (gst_element_link_pads(subparse, "src", textoverlay, "subtitle-sink")) 
    perror("***error: Pads couldn't be linked\n");

【问题讨论】:

过去的你好。不错的话题。我找到了阅读您的问题的解决方案。谢谢你。但我能问点什么吗?您正在注册回调函数以检测视频文件中的焊盘。可以在管道启动之前完成吗?例如,make filesrc 和 demuxer。然后链接它们。并运行“初始化”。因此,解复用器现在知道他将拥有多少个焊盘。我想避免的想法是拆分代码,当一个函数(从文件读取)中完成一个管道和平,另一个(解码和播放)完成另一个管道时,但所有这些都在第三位链接在一起。 【参考方案1】:

你只需要添加:

g_object_set (G_OBJECT (source_sub), "location", argv[2], NULL);

在您的第一个解决方案中,它应该可以工作(除非您不提供字幕,在这种情况下,您应该检查它们是否存在并链接/取消链接元素)。

然后要在播放期间激活/停用字幕,您必须使用 subtitleoverlay 中的“静音”属性播放。

祝你好运!

【讨论】:

嗨!感谢您的回答,自从我发布这个问题以来,我解决了我的问题;事实上,我使用了静默属性,它工作正常。再次感谢,祝你有美好的一天:-)

以上是关于如何在 C 程序中使用 Gstreamer 在视频中动态添加和删除字幕的主要内容,如果未能解决你的问题,请参考以下文章

如何在 python TKinter 中使用 GStreamer 在视频播放器中调整大小和裁剪?

如何在 Qt 中实现基于 GStreamer 的视频小部件?

如何将 gstreamer 1.0 视频元素添加到 qt5 应用程序

如何在 gstreamer 中混合音频和视频

如何在gstreamer中录制音频和视频

GTK3.0中如何使用gstreamer同时播放视频和音频