Esempio n. 1
0
        public override async Task stream(StreamRequest request, IServerStreamWriter <VideoChunk> responseStream, ServerCallContext context)
        {
            var findResult = await _repo.FindById(request.VideoId);

            if (findResult == null)
            {
                throw new RpcException(new Status(StatusCode.NotFound, "Video not found"));
            }

            var downloadRequest = new DownloadRequest
            {
                Id      = findResult.ExternalFileId,
                Options = new FileOptions
                {
                    Start = 0
                }
            };

            var remoteStream = _fileServerClient.download(downloadRequest);
            var fileStream   = remoteStream.ResponseStream;

            while (await fileStream.MoveNext(context.CancellationToken))
            {
                var chunk = fileStream.Current.Chunk;

                // TODO: Transcode Chunk

                await responseStream.WriteAsync(new VideoChunk { VideoId = request.VideoId, Chunk = chunk });
            }
        }
Esempio n. 2
0
        public override async Task stream(StreamRequest request, IServerStreamWriter <VideoChunk> responseStream, ServerCallContext context)
        {
            var findResult = await _repo.FindById(request.VideoId);

            if (findResult == null)
            {
                throw new RpcException(new Status(StatusCode.NotFound, "Video not found"));
            }

            if (!string.IsNullOrWhiteSpace(findResult.ExternalFileId))
            {
                var downloadRequest = new DownloadRequest
                {
                    Id      = findResult.ExternalFileId,
                    Options = new FileOptions
                    {
                        Start = 0
                    }
                };

                var remoteStream = _fileServerClient.download(downloadRequest);
                var fileStream   = remoteStream.ResponseStream;

                while (await fileStream.MoveNext(context.CancellationToken))
                {
                    var chunk = fileStream.Current.Chunk;

                    // TODO: Transcode Chunk

                    await responseStream.WriteAsync(new VideoChunk { VideoId = request.VideoId, Chunk = chunk });
                }
            }
            else if (!string.IsNullOrWhiteSpace(findResult.StreamName))
            {
                var subscriber = _redisMultiplexer.GetSubscriber();

                var observable = Observable.Create <VideoChunk>(async(obs, ct) =>
                {
                    var channel = findResult.StreamName;
                    await subscriber.SubscribeAsync(channel, (_, message) =>
                    {
                        obs.OnNext(FromRedisValue(message));
                    }).ConfigureAwait(false);

                    return(Disposable.Create(() => subscriber.Unsubscribe(channel)));
                });


                var breakCount = 0;
                using (var subscription = observable.Subscribe(async(message) =>
                {
                    try
                    {
                        if (breakCount < 3)
                        {
                            await responseStream.WriteAsync(message);
                            breakCount = 0;
                        }
                    }
                    catch (Exception e)
                    {
                        breakCount++;
                        _logger.LogError(e, "Error while writing video chunk to response.");
                    }
                }))
                {
                    _logger.LogInformation("User {UserId} subscribed to video {VideoId}", request.UserId, request.VideoId);
                    //This is to prevent the response stream from being disposed
                    while (breakCount < 3)
                    {
                        await Task.Delay(1000);
                    }
                }
            }
        }