Exemple #1
0
        /// <inheritdoc />
        public Task <MediaStream> GetMediaStreamAsync(MediaStreamInfo info)
        {
            info.GuardNotNull(nameof(info));

            // Determine if stream is rate-limited
            var isRateLimited = !Regex.IsMatch(info.Url, "ratebypass[=/]yes");

            // Determine segment size
            var segmentSize = isRateLimited
                ? 9_898_989      // this number was carefully devised through research
                : long.MaxValue; // don't use segmentation for non-rate-limited streams

            // Get segmented stream
            var stream = _httpClient.CreateSegmentedStream(info.Url, info.Size, segmentSize);

            // This method must return a task for backwards-compatibility reasons
            return(Task.FromResult(new MediaStream(info, stream)));
        }
        /// <summary>
        /// Gets the actual media stream associated with given metadata
        /// and downloads it to a file.
        /// </summary>
        public async Task DownloadMediaStreamAsync(MediaStreamInfo info, string filePath,
                                                   IProgress <double> progress, CancellationToken cancellationToken)
        {
            info.GuardNotNull(nameof(info));
            filePath.GuardNotNull(nameof(filePath));

            // Keep track of bytes copied for progress reporting
            var totalBytesCopied = 0L;

            // Determine if stream is rate-limited
            var isRateLimited = !Regex.IsMatch(info.Url, @"ratebypass[=/]yes");

            // Download rate-limited streams in segments
            if (isRateLimited)
            {
                // Determine segment count
                const long segmentSize  = 9_898_989; // this number was carefully devised through research
                var        segmentCount = (int)Math.Ceiling(1.0 * info.Size / segmentSize);

                using (var output = File.Create(filePath))
                {
                    for (var i = 0; i < segmentCount; i++)
                    {
                        // Determine segment range
                        var from = i * segmentSize;
                        var to   = (i + 1) * segmentSize - 1;

                        // Create request with range
                        var request = new HttpRequestMessage(HttpMethod.Get, info.Url);
                        request.Headers.Range = new RangeHeaderValue(from, to);

                        // Download segment
                        using (request)
                            using (var response = await _httpService.PerformRequestAsync(request).ConfigureAwait(false))
                                using (var input = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                                {
                                    int bytesCopied;
                                    do
                                    {
                                        // Copy
                                        bytesCopied = await input.CopyChunkToAsync(output, cancellationToken)
                                                      .ConfigureAwait(false);

                                        // Report progress
                                        totalBytesCopied += bytesCopied;
                                        progress?.Report(1.0 * totalBytesCopied / info.Size);
                                    } while (bytesCopied > 0);
                                }
                    }
                }
            }
            // Download non-limited streams directly
            else
            {
                using (var output = File.Create(filePath))
                    using (var input = await GetMediaStreamAsync(info).ConfigureAwait(false))
                    {
                        int bytesCopied;
                        do
                        {
                            // Copy
                            bytesCopied = await input.CopyChunkToAsync(output, cancellationToken)
                                          .ConfigureAwait(false);

                            // Report progress
                            totalBytesCopied += bytesCopied;
                            progress?.Report(1.0 * totalBytesCopied / info.Size);
                        } while (bytesCopied > 0);
                    }
            }
        }