我正在编写自己的(简单)HLS实现,为此,我需要下载MPEG传输流视频文件列表:
现在,我有这个,它有效:
public async Task<IObservable<(int Current, int Total, Stream Stream)>> FetchVideoSegments()
{
var playlist = await GetPlaylist();
var total = playlist.PlaylistItems.Count();
return playlist.PlaylistItems.ToObservable()
//=> Get the video file path, relative to the current playlist URI
.Select(item => item.Uri)
//=> Convert the relative URI to an absolute one
.Select(MakeRelativeAbsoluteUrl)
//=> Download the video transport file, sequentially
.Select(uri => Observable.Defer(() => DownloadVideoSegment(uri)))
.Concat()
//=> Return the progress info tuple with the video file stream
.Select((stream, index) => (index, total, stream));
}
按顺序通知订户,一次一个流。
通常,在下载文件时,2-3的并发性通常是理想的。我想将它添加到我的可观察管道中,但是我没有看到任何有效的方法来保持原始URI在发出的流中的插入顺序。
拿这个:
return playlist.PlaylistItems.ToObservable()
//=> Get the video file path, relative to the current playlist URI
.Select(item => item.Uri)
//=> Convert the relative URI to an absolute one
.Select(MakeRelativeAbsoluteUrl)
//=> Download the video transport file
.Select(uri => Observable.Defer(() => DownloadVideoSegment(uri)))
//=> Limit concurrent requests to a reasonable number
.Merge(FetchSegmentsMaxConcurrency)
//=> Return the progress info tuple with the video file stream
.Select((stream, index) => (index, total, stream));
请注意,.Concat()
已替换为.Merge(maxConcurrency)
。
这是天真的解决方案,当然它不起作用:视频流以非确定性顺序发出。
实现这一目标的规范方法是什么?我应该保留另一个通过可观察管道保留的“索引”值吗?
答案 0 :(得分:0)
这样的事情会是你想要的吗?当然,将char
替换为DownloadVideoSegment
返回的任何内容。
var random = new Random();
Observable
.Range(65, 26)
.Select(char.ConvertFromUtf32)
.Select((letter, index) =>
Observable
.FromAsync(() =>
Task.Delay(random.Next(5000))
.ContinueWith(t => (letter, index))))
.Merge()
.Do(tuple => Console.WriteLine($"{tuple.letter}:{tuple.index}"))
.Buffer(Observable.Never<Unit>())
.Subscribe(tuples =>
Console.WriteLine($"{string.Join(",", tuples.OrderBy(t => t.index).Select(t => t.letter))}"));