/// <summary> /// Writes the actual closed caption track which is identified by the specified metadata to the specified writer. /// Closed captions are written in the SRT file format. /// </summary> public async Task WriteToAsync(ClosedCaptionTrackInfo trackInfo, TextWriter writer, IProgress <double>?progress = null, CancellationToken cancellationToken = default) { var track = await GetAsync(trackInfo); var buffer = new StringBuilder(); for (var i = 0; i < track.Captions.Count; i++) { var caption = track.Captions[i]; buffer.Clear(); cancellationToken.ThrowIfCancellationRequested(); // 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); await writer.WriteLineAsync(buffer.ToString()); progress?.Report((i + 1.0) / track.Captions.Count); } }
/// <summary> /// Downloads the closed caption track identified by the specified metadata to the specified file. /// </summary> /// <remarks> /// Closed captions are written in the SRT file format. /// </remarks> public async ValueTask DownloadAsync( ClosedCaptionTrackInfo trackInfo, string filePath, IProgress <double>?progress = null, CancellationToken cancellationToken = default) { using var writer = File.CreateText(filePath); await WriteToAsync(trackInfo, writer, progress, cancellationToken); }
/// <summary> /// Gets the closed caption track identified by the specified metadata. /// </summary> public async ValueTask <ClosedCaptionTrack> GetAsync( ClosedCaptionTrackInfo trackInfo, CancellationToken cancellationToken = default) { var trackExtractor = await _controller.GetClosedCaptionTrackAsync(trackInfo.Url, cancellationToken); var captions = trackExtractor .GetClosedCaptions() .Select(c => { var text = c.TryGetText(); if (string.IsNullOrWhiteSpace(text)) { return(null); } var offset = c.TryGetOffset() ?? throw new YoutubeExplodeException("Could not extract caption offset."); var duration = c.TryGetDuration() ?? throw new YoutubeExplodeException("Could not extract caption duration."); var parts = c .GetParts() .Select(p => { var partText = p.TryGetText(); if (string.IsNullOrWhiteSpace(partText)) { return(null); } var partOffset = p.TryGetOffset() ?? throw new YoutubeExplodeException("Could not extract caption part offset."); return(new ClosedCaptionPart(partText, partOffset)); }) .WhereNotNull() .ToArray(); return(new ClosedCaption(text, offset, duration, parts)); }) .WhereNotNull() .ToArray(); return(new ClosedCaptionTrack(captions)); }
/// <summary> /// Gets the actual closed caption track which is identified by the specified metadata. /// </summary> public async Task <ClosedCaptionTrack> GetAsync(ClosedCaptionTrackInfo trackInfo) { var response = await ClosedCaptionTrackResponse.GetAsync(_httpClient, trackInfo.Url); var captions = response.GetClosedCaptions() .Where(t => !string.IsNullOrWhiteSpace(t.GetText())) .Select(t => new ClosedCaption( t.GetText(), t.GetOffset(), t.GetDuration() )).ToArray(); return(new ClosedCaptionTrack(captions)); }