通过发布/订阅的视频流:哪种视频编码支持c#和HTML5的实时流媒体?

ssgvzors  于 2021-06-07  发布在  Kafka
关注(0)|答案(0)|浏览(271)

忙着用HTML5通过ApacheKafka将网络摄像头视频发布到web(nancyfxC#)客户端的展示/测试。我知道生成的视频流总是有几秒钟的延迟。但我希望使用最新的网络(HTML5)、流媒体(kafka)和视频(webm?)技术,尽可能快地实现解决方案。
Kafka的部分,包括生产者和消费者,正在工作:使用http://www.aforgenet.com/framework/. 我可以用这个库在磁盘上创建一个视频文件,但没有流。
当我使用这个webm(vp9)视频文件作为部分http内容(谢谢:http://richardssoftware.net/home/post/61)它在浏览器中工作。这很好,因为您知道前面的总(文件)长度。
但是现在用HTML5将jpeg帧图像实时流式传输到视频播放器似乎不那么容易。
我的问题:
HTML5视频播放器是否支持流式视频:没有定义端点的视频?
哪种视频编码最适合直播?我目前正在测试webm(vp9),但没有现场视频流的经验。
使用nancyfx的部分http内容似乎支持视频时间滑块偏移。但它是否也可用于实时视频流?可能使用Kafka偏移1对1或帧id/关键帧作为滑块值?
到目前为止我的代码是:
Kafka制作人在c#使用forge.net lib捕获视频摄像机:

class Program
{
    const string brokerList = "127.0.0.1:2181";
    const string topicName = "video_test";

    static IDictionary<string, object> config = new Dictionary<string, object>
    {
        {"bootstrap.servers", "notebook039:9092" },
        {"retries", 0 },
        {"client.id", 200677},
        {"batch.num.messages", 1},
        {"socket.blocking.max.ms", 1},
        {"socket.nagle.disable", true},
        {"queue.buffering.max.ms", 0},
        {"default.topic.config", new Dictionary<string, object>
            {
                {"acks", 1}
            }
        }
    };

    static Lazy<Producer<long, Bitmap>> publisher = 
        new Lazy<Producer<long, Bitmap>>(() => new Producer<long, Bitmap>(
                        config, 
                        new LongSerializer(), 
                        new BitmapSerializer()), true);

    static long frameId = 0;

    static private async void video_NewFrame(
                                            object sender,
                                            NewFrameEventArgs eventArgs)
    {
        try
        {
            // get new frame
            Bitmap bitmap = eventArgs.Frame;

            // process the frame
            publisher.Value.ProduceAsync(topicName, ++frameId, bitmap, null);

            if ((frameId % 24 == 0))
            {
                Console.WriteLine($"frameId: {frameId}");
            }
        }
        catch ( Exception ex )
        {
            Console.WriteLine($"Error: " + ex.Message);
        }
    }

    static void Main(string[] args)
    {

        var cancelled = false;
        Console.CancelKeyPress += (_, e) =>
        {
            e.Cancel = true; // prevent the process from terminating.
                cancelled = true;
        };

        // enumerate video devices
        var videoDevices = new FilterInfoCollection(
                        FilterCategory.VideoInputDevice);

        // create video source
        VideoCaptureDevice videoSource = new VideoCaptureDevice(
                        videoDevices[0].MonikerString);

        // set NewFrame event handler
        videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);

        // start the video source
        videoSource.Start();

        while (!cancelled)
        {
            Console.Write("> ");

            Thread.Sleep(TimeSpan.FromSeconds(1));
        }

        // signal to stop
        videoSource.SignalToStop();
    }
}

南希模块订阅Kafka视频主题:

public class KafkaCam : NancyModule
{
    const string brokerList = "notebook039:2181";
    const string topicName = "video_test";

    static IDictionary<string, object> config = new Dictionary<string, object>
    {
        {"group.id", Guid.NewGuid().ToString()},
        { "auto.offset.reset", "latest" },
        { "bootstrap.servers", "notebook039:9092" },
        {"retries", 0 },
        {"client.id", 210677},
        {"batch.num.messages", 1},
        {"socket.blocking.max.ms", 1},
        {"socket.nagle.disable", true},
        {"queue.buffering.max.ms", 0},
        {"default.topic.config", new Dictionary<string, object>
            {
                {"acks", 1}
            }
        }
    };

    static Lazy<Consumer<long, Bitmap>> subscriber =
    new Lazy<Consumer<long, Bitmap>>(
        () => new Consumer<long, Bitmap>(
                            config,
                            new LongDeserializer(),
                            new BitmapDeserializer()),
        true);

    const string videoFilePath = @"D:\Kafka\clients\KafkaPublishSubscribeTests\data\video.webm";

    Accord.Video.FFMPEG.VideoFileWriter videoFile = new Accord.Video.FFMPEG.VideoFileWriter();

    public void FramesWriter()
    {
        try
        {
            Message<long, Bitmap> message = null;
            subscriber.Value.Subscribe(topicName);

            if (!videoFile.IsOpen)
            {
                videoFile.Open(videoFilePath, 640, 480, 24, Accord.Video.FFMPEG.VideoCodec.VP9);
            }

            do
            {
                subscriber.Value.Poll(TimeSpan.FromSeconds(2));

                if (subscriber.Value.Consume(out message, TimeSpan.FromSeconds(2)) 
                        && message != null )
                {
                    videoFile.WriteVideoFrame(message.Value, (uint)message.Key);
                    videoFile.Flush();
                }
            }
            while (true);

        }
        catch ( Exception ex )
        {
            throw ex;
        }
        finally
        {
            videoFile.Close();
            videoFile = null;
        }
    }

    public KafkaCam()
    {
        Task.Factory.StartNew(FramesWriter);

        Get["/Camera.webm"] = parameters =>
        {
            return Response.FromPartialFile(Request, videoFilePath, "video/webm");
        };
    }
}

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题