diff options
| author | crobibero <cody@robibe.ro> | 2020-09-11 15:53:04 -0600 |
|---|---|---|
| committer | crobibero <cody@robibe.ro> | 2020-09-11 15:53:04 -0600 |
| commit | f13b87afa3e81e7fa2710caec58a7d6cb20f7635 (patch) | |
| tree | 0f269ac5baa27b334c5377d9dec4010aedf25183 /Jellyfin.Api/Helpers/HlsHelpers.cs | |
| parent | 2363ad544979adf32207fa927f106fadb784f1fb (diff) | |
| parent | 6bf0acb854683377bebad3ca27de17706519c420 (diff) | |
Merge remote-tracking branch 'upstream/master' into api-upload-subtitle
Diffstat (limited to 'Jellyfin.Api/Helpers/HlsHelpers.cs')
| -rw-r--r-- | Jellyfin.Api/Helpers/HlsHelpers.cs | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs new file mode 100644 index 000000000..242496697 --- /dev/null +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -0,0 +1,95 @@ +using System; +using System.Globalization; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.IO; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Api.Helpers +{ + /// <summary> + /// The hls helpers. + /// </summary> + public static class HlsHelpers + { + /// <summary> + /// Waits for a minimum number of segments to be available. + /// </summary> + /// <param name="playlist">The playlist string.</param> + /// <param name="segmentCount">The segment count.</param> + /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param> + /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param> + /// <returns>A <see cref="Task"/> indicating the waiting process.</returns> + public static async Task WaitForMinimumSegmentCount(string playlist, int? segmentCount, ILogger logger, CancellationToken cancellationToken) + { + logger.LogDebug("Waiting for {0} segments in {1}", segmentCount, playlist); + + while (!cancellationToken.IsCancellationRequested) + { + try + { + // Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written + var fileStream = new FileStream( + playlist, + FileMode.Open, + FileAccess.Read, + FileShare.ReadWrite, + IODefaults.FileStreamBufferSize, + FileOptions.SequentialScan); + await using (fileStream.ConfigureAwait(false)) + { + using var reader = new StreamReader(fileStream); + var count = 0; + + while (!reader.EndOfStream) + { + var line = await reader.ReadLineAsync().ConfigureAwait(false); + + if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1) + { + count++; + if (count >= segmentCount) + { + logger.LogDebug("Finished waiting for {0} segments in {1}", segmentCount, playlist); + return; + } + } + } + } + + await Task.Delay(100, cancellationToken).ConfigureAwait(false); + } + catch (IOException) + { + // May get an error if the file is locked + } + + await Task.Delay(50, cancellationToken).ConfigureAwait(false); + } + } + + /// <summary> + /// Gets the hls playlist text. + /// </summary> + /// <param name="path">The path to the playlist file.</param> + /// <param name="segmentLength">The segment length.</param> + /// <returns>The playlist text as a string.</returns> + public static string GetLivePlaylistText(string path, int segmentLength) + { + using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using var reader = new StreamReader(stream); + + var text = reader.ReadToEnd(); + + text = text.Replace("#EXTM3U", "#EXTM3U\n#EXT-X-PLAYLIST-TYPE:EVENT", StringComparison.InvariantCulture); + + var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(CultureInfo.InvariantCulture); + + text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength - 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase); + // text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase); + + return text; + } + } +} |
