From c1f9107b8be9b3cbd26e15773998c7ac6598e7f9 Mon Sep 17 00:00:00 2001 From: Vasily Date: Thu, 3 Oct 2019 18:50:39 +0300 Subject: [PATCH] Add more logging Trying to fix hls muxer plus ffmpeg 4.1+ combo Try to fix waiting for segment being ready This is needed because hls muxer in ffmpeg >= 4.1 creates the playlist only when it finishes transcoding. Also cleaned up logs a bit. Lower log level for "StartFfmpeg finished" to debug --- .../Playback/BaseStreamingService.cs | 7 ++- .../Playback/Hls/DynamicHlsService.cs | 47 ++++++++----------- deployment/debian-package-x64/docker-build.sh | 1 + 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 8c4ccfa22c..700883c963 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -289,16 +289,20 @@ namespace MediaBrowser.Api.Playback throw; } + Logger.LogDebug("Launched ffmpeg process"); state.TranscodingJob = transcodingJob; // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback _ = new JobLogger(Logger).StartStreamingLog(state, process.StandardError.BaseStream, logStream); // Wait for the file to exist before proceeeding - while (!File.Exists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited) + var waitFor = state.WaitForPath ?? outputPath; + Logger.LogDebug("Waiting for the creation of '{0}'", waitFor); + while (!File.Exists(waitFor) && !transcodingJob.HasExited) { await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false); } + Logger.LogDebug("File '{0}' created or transcoding has finished", waitFor); if (state.IsInputVideo && transcodingJob.Type == TranscodingJobType.Progressive && !transcodingJob.HasExited) { @@ -314,6 +318,7 @@ namespace MediaBrowser.Api.Playback { StartThrottler(state, transcodingJob); } + Logger.LogDebug("StartFfMpeg() finished successfully"); return transcodingJob; } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 8fa6c3dac0..15dd5add4a 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -243,6 +243,7 @@ namespace MediaBrowser.Api.Playback.Hls request.StartTimeTicks = GetStartPositionTicks(state, requestedIndex); + state.WaitForPath = segmentPath; job = await StartFfMpeg(state, playlistPath, cancellationTokenSource).ConfigureAwait(false); } catch @@ -458,16 +459,15 @@ namespace MediaBrowser.Api.Playback.Hls TranscodingJob transcodingJob, CancellationToken cancellationToken) { - var segmentFileExists = File.Exists(segmentPath); - - // If all transcoding has completed, just return immediately - if (transcodingJob != null && transcodingJob.HasExited && segmentFileExists) + var segmentExists = File.Exists(segmentPath); + if (segmentExists) { - return await GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob).ConfigureAwait(false); - } + if (transcodingJob != null && transcodingJob.HasExited) + { + // Transcoding job is over, so assume all existing files are ready + return await GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob).ConfigureAwait(false); + } - if (segmentFileExists) - { var currentTranscodingIndex = GetCurrentTranscodingIndex(playlistPath, segmentExtension); // If requested segment is less than transcoding position, we can't transcode backwards, so assume it's ready @@ -477,33 +477,26 @@ namespace MediaBrowser.Api.Playback.Hls } } - var segmentFilename = Path.GetFileName(segmentPath); - + var nextSegmentPath = GetSegmentPath(state, playlistPath, segmentIndex + 1); while (!cancellationToken.IsCancellationRequested) { - try + // To be considered ready, the segment file has to exist AND + // either the transcoding job should be done or next segment should also exit + if (segmentExists) { - var text = File.ReadAllText(playlistPath, Encoding.UTF8); - - // If it appears in the playlist, it's done - if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1) + if ((transcodingJob != null && transcodingJob.HasExited) || File.Exists(nextSegmentPath)) { - if (!segmentFileExists) - { - segmentFileExists = File.Exists(segmentPath); - } - if (segmentFileExists) - { - return await GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob).ConfigureAwait(false); - } - //break; + return await GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob).ConfigureAwait(false); } } - catch (IOException) + else { - // May get an error if the file is locked + segmentExists = File.Exists(segmentPath); + if (segmentExists) + { + continue; // avoid unnecessary waiting if segment just became available + } } - await Task.Delay(100, cancellationToken).ConfigureAwait(false); } diff --git a/deployment/debian-package-x64/docker-build.sh b/deployment/debian-package-x64/docker-build.sh index 97bc45a060..5911923d78 100755 --- a/deployment/debian-package-x64/docker-build.sh +++ b/deployment/debian-package-x64/docker-build.sh @@ -20,6 +20,7 @@ if [[ -n ${web_branch} ]]; then checkout -b origin/${web_branch} fi yarn install +yarn build mkdir -p ${web_target} mv dist/* ${web_target}/ popd