忙着用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");
};
}
}
暂无答案!
目前还没有任何答案,快来回答吧!