/// <inheritdoc /> public async Task <ClosedCaptionTrack> GetClosedCaptionTrackAsync(ClosedCaptionTrackInfo info) { info.EnsureNotNull(nameof(info)); // Get manifest var raw = await _httpClient.GetStringAsync(info.Url).ConfigureAwait(false); var trackXml = XElement.Parse(raw).StripNamespaces(); // Parse captions var captions = new List <ClosedCaption>(); foreach (var captionXml in trackXml.Descendants("p")) { var text = (string)captionXml; if (text.IsBlank()) { continue; // some autogenerated captions are blank } var offset = TimeSpan.FromMilliseconds((double)captionXml.Attribute("t")); var duration = TimeSpan.FromMilliseconds((double)captionXml.Attribute("d")); var caption = new ClosedCaption(text, offset, duration); captions.Add(caption); } return(new ClosedCaptionTrack(info, captions)); }
/// <inheritdoc /> public async Task DownloadClosedCaptionTrackAsync(ClosedCaptionTrackInfo info, Stream output, IProgress <double> progress = null, CancellationToken cancellationToken = default(CancellationToken)) { info.EnsureNotNull(nameof(info)); output.EnsureNotNull(nameof(output)); // Get the track var track = await GetClosedCaptionTrackAsync(info).ConfigureAwait(false); // Save to file as SRT using (var writer = new StreamWriter(output, Encoding.UTF8, 1024, true)) { for (var i = 0; i < track.Captions.Count; i++) { // Make sure cancellation was not requested cancellationToken.ThrowIfCancellationRequested(); var caption = track.Captions[i]; var buffer = new StringBuilder(); // Line number buffer.AppendLine((i + 1).ToString()); // Time start --> time end buffer.Append(caption.Offset.ToString(@"hh\:mm\:ss\,fff")); buffer.Append(" --> "); buffer.Append((caption.Offset + caption.Duration).ToString(@"hh\:mm\:ss\,fff")); buffer.AppendLine(); // Actual text buffer.AppendLine(caption.Text); // Write to stream await writer.WriteLineAsync(buffer.ToString()).ConfigureAwait(false); // Report progress progress?.Report((i + 1.0) / track.Captions.Count); } } }