【问题标题】:Looping a video with gstreamer and gst-launch?使用 gstreamer 和 gst-launch 循环播放视频?
【发布时间】:2011-10-13 13:44:18
【问题描述】:

我可以使用 gstreamer 的gst-launch 在命令行上播放视频,如下所示:

gst-launch gnlfilesource location=file:///tmp/myfile.mov start=0 duration=2000000000 ! autovideosink

这将播放 /tmp/myfile.mov 中文件的前 2 秒,然后视频播放停止。反正有没有让这个循环重复?即将 2 秒长的 gnlfilesource 变成无限长的视频,一遍又一遍地播放这 2 秒?

【问题讨论】:

    标签: linux video video-processing gstreamer gnonlin


    【解决方案1】:

    multifilesrc 是最简单的方法,但它不适用于已知“媒体长度”的媒体文件。只有当文件没有关于时间或长度的任何信息时,您才能循环播放任何视频文件。

    用任何媒体播放器打开您的文件,如果它显示媒体长度或者您可以向前或向后查找文件,这意味着它知道媒体长度并且multifilesrc 不会循环播放。

    如何使用 GStreamer 将视频文件转换为没有时间轨迹的文件(流文件):

    你需要在命令行运行两条管道,首先运行记录器:

    gst-launch-1.0 udpsrc port=10600 ! application/x-rtp-stream ! rtpstreamdepay name=pay1 ! rtph264depay ! h264parse ! video/x-h264,alignment=nal ! filesink location=my_timeless_file.mp4
    

    它启动并等待传入​​流。

    在另一个终端上运行播放管道:

    gst-launch-1.0 filesrc location=my_file_with_time_track ! queue ! decodebin ! videoconvert ! x264enc ! h264parse config-interval=-1 ! rtph264pay pt=96 ! rtpstreampay name=pay0 ! udpsink host=127.0.0.1 port=10600
    

    播放管道在流式传输整个文件时开始并最终终止,现在返回第一个命令行并使用 Ctrl+C 终止录制管道。

    (除了 udpsrc/udpsink,您可以使用任何其他机制来制作流,例如 appsrc/appsink)

    现在您有了一个新文件,可以在 multifilesrc 中使用循环:

    gst-launch-1.0 multifilesrc location=my_timeless_file.mp4 loop=true ! queue ! decodebin ! videoconvert ! ximagesink
    

    为什么multifilesrc 不循环已知长度的文件?

    因为当媒体长度已知时,它会向下游发送 EOS 消息并导致整个管道进入状态 NULL,通过在到达文件末尾(字节流)时删除该信息,它会尝试查找下一个要播放的文件(记住它是"multi" 文件源,默认情况下可以接受通配符位置,如 "image_%d.png")。当没有通配符指向下一个文件时,它会循环回唯一的已知文件。

    【讨论】:

      【解决方案2】:

      它不是在 gstreamer 上的流中循环文件,但我可以使用 ffmpeg -stream_loop 选项来做到这一点。 https://ffmpeg.org/ffmpeg.html#Main-options

      $ ffmpeg -re -stream_loop -1 -i /tmp/sample.mp4 -f rtsp rtsp://localhost:8554/stream
      

      【讨论】:

      • 在尝试处理此问题时遇到 Connection to tcp://localhost:8554?timeout=0 failed (Connection refused), trying next address 错误,
      【解决方案3】:

      这似乎可以通过multifilesrc 插件实现,

      gst-launch-1.0 multifilesrc location=alien-age.mpg loop=true ! decodebin ! autovideosink
      

      似乎是在 2011 年 6 月添加回来的。

      【讨论】:

      • 在使用 v4l2loopback 的浏览器中将视频作为网络摄像头流式传输时,不会在 Ubuntu 18.04 上循环播放。
      • 对我来说也不适用于 Ubuntu18.04 和 Ubuntu20.04
      【解决方案4】:

      如果使用 gst-launch,那么您可能必须使用 while true; do [your command]; done,正如 Fredrik 所说的那样。但是,如果对 C 代码感兴趣,我已经编写了一个可以帮助您的代码。在第一次运行的流结束时,从文件开头开始每 2 秒循环一次视频。

        //(c) 2011 enthusiasticgeek
        // This code is distributed in the hope that it will be useful,
        // but WITHOUT ANY WARRANTY; without even the implied warranty of
        // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      
      #include <gst/gst.h>
      
      gboolean bus_callback(GstBus *bus, GstMessage *msg, gpointer data)
      {
          GstElement *play = GST_ELEMENT(data);
          switch (GST_MESSAGE_TYPE(msg))
          {
          case GST_MESSAGE_EOS:
              /* restart playback if at end */
              if (!gst_element_seek(play, 
                          1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
                          GST_SEEK_TYPE_SET,  2000000000, //2 seconds (in nanoseconds)
                          GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
                  g_print("Seek failed!\n");
              }
              break;
          default:
              break;
          }
          return TRUE;
      }
      
      gint
      main (gint   argc,
            gchar *argv[])
      {
        GMainLoop *loop;
        GstElement *play;
        GstBus *bus;
      
        /* init GStreamer */
        gst_init (&argc, &argv);
        loop = g_main_loop_new (NULL, FALSE);
      
        /* make sure we have a URI */
        if (argc != 2) {
          g_print ("Usage: %s <URI>\n", argv[0]);
          return -1;
        }
      
        /* set up */
        play = gst_element_factory_make ("playbin", "play");
        g_object_set (G_OBJECT (play), "uri", argv[1], NULL);
      
        bus = gst_pipeline_get_bus (GST_PIPELINE (play));
        gst_bus_add_watch (bus, bus_callback, play);
        gst_object_unref (bus);
      
        gst_element_set_state (play, GST_STATE_PLAYING);
      
        /* now run */
        g_main_loop_run (loop);
      
        /* also clean up */
        gst_element_set_state (play, GST_STATE_NULL);
        gst_object_unref (GST_OBJECT (play));
      
        return 0;
      }
      

      更新: 请参阅以下链接 http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-dataaccess.html

      [第 19.1.2 节。播放媒体文件的一个区域]。这可以与我的代码结合使用。

      【讨论】:

      • 有趣的是,这个解决方案的时间戳并不是单调递增的。
      • 你如何使用它来实际播放 gstreamer 视频?!当我启动那个二进制文件时,什么都没有发生......
      【解决方案5】:

      根据#gstreamer IRC 频道上的人们所说,您无法使用 gstreamer 本身执行此操作,您需要在 gstreamer 管道之外进行循环。

      【讨论】:

        【解决方案6】:

        假设 bash...

        将其包装在while-loop 中?

        while true; do [your command]; done
        

        true 没有成功执行任何操作,即

        true: true
            Return a successful result.
        
            Exit Status:
            Always succeeds.
        

        它允许您创建无限循环,例如

        $ while true; do echo "run..."; sleep 1; done
        run...
        run...
        run...
        run...
        run...
        ...
        

        【讨论】:

        • Pedically 这会起作用,但我想在 gstreamer 中完成,以便稍后处理这个无限循环......
        • @Rory - 抱歉,帮不了你,谷歌搜索“gst-launch looping video”会返回一些有趣的匹配...
        • 在 videomixer 内循环可变长度的视频时失败。
        • 这看起来更像是一个快速修复而不是解决方案
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多