Restart ffmpeg if it crashes? Maybe i should reconsider file-based cache. Ffmpeg doesn't like being slowed down it seems

This commit is contained in:
Master Kwoth 2017-07-04 11:23:34 +02:00
parent 842b45178d
commit 556174ec89

View File

@ -19,20 +19,14 @@ namespace NadekoBot.Services.Music
public string SongUri { get; private set; } public string SongUri { get; private set; }
private volatile bool restart = false;
public SongBuffer(string songUri, string skipTo) public SongBuffer(string songUri, string skipTo)
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
this.SongUri = songUri; this.SongUri = songUri;
this.p = Process.Start(new ProcessStartInfo this.p = StartFFmpegProcess(songUri, 0);
{
FileName = "ffmpeg",
Arguments = $"-i {songUri} -f s16le -ar 48000 -vn -ac 2 pipe:1 -loglevel error -threads 0 -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
});
var t = Task.Run(() => var t = Task.Run(() =>
{ {
this.p.BeginErrorReadLine(); this.p.BeginErrorReadLine();
@ -41,9 +35,27 @@ namespace NadekoBot.Services.Music
}); });
} }
private Process StartFFmpegProcess(string songUri, float skipTo = 0)
{
return Process.Start(new ProcessStartInfo
{
FileName = "ffmpeg",
Arguments = $"-ss {skipTo:F4} -i {songUri} -f s16le -ar 48000 -vn -ac 2 pipe:1 -loglevel error -threads 0 -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
});
}
private void P_ErrorDataReceived(object sender, DataReceivedEventArgs e) private void P_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{ {
_log.Error(">>> " + e.Data); _log.Error(">>> " + e.Data);
if (e.Data.Contains("Error in the pull function"))
{
_log.Info("Got error in the pull function!");
restart = true;
}
} }
private readonly object locker = new object(); private readonly object locker = new object();
@ -56,39 +68,57 @@ namespace NadekoBot.Services.Music
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
var delay = 1000 / maxLoopsPerSec; var delay = 1000 / maxLoopsPerSec;
int currentLoops = 0; int currentLoops = 0;
int _bytesSent = 0;
try try
{ {
++currentLoops; do
byte[] buffer = new byte[readSize];
int bytesRead = 1;
while (!cancelToken.IsCancellationRequested && !this.p.HasExited)
{ {
bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, readSize, cancelToken).ConfigureAwait(false); if (restart)
if (bytesRead == 0)
break;
bool written;
do
{ {
lock (locker) var cur = _bytesSent / 3840 / (1000 / 20.0f);
written = _outStream.Write(buffer, 0, bytesRead); _log.Info("Restarting");
if (!written) try { this.p.StandardOutput.Dispose(); } catch { }
await Task.Delay(2000, cancelToken); try { this.p.Dispose(); } catch { }
this.p = StartFFmpegProcess(SongUri, cur);
} }
while (!written); restart = false;
lock (locker) ++currentLoops;
if (_outStream.Length > 200_000 || bytesRead == 0) byte[] buffer = new byte[readSize];
if (toReturn.TrySetResult(true)) int bytesRead = 1;
_log.Info("Prebuffering finished in {0}", sw.Elapsed.TotalSeconds.ToString("F2")); while (!cancelToken.IsCancellationRequested && !this.p.HasExited)
{
bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, readSize, cancelToken).ConfigureAwait(false);
_bytesSent += bytesRead;
if (bytesRead == 0)
break;
bool written;
do
{
lock (locker)
written = _outStream.Write(buffer, 0, bytesRead);
if (!written)
await Task.Delay(2000, cancelToken);
}
while (!written);
lock (locker)
if (_outStream.Length > 200_000 || bytesRead == 0)
if (toReturn.TrySetResult(true))
_log.Info("Prebuffering finished in {0}", sw.Elapsed.TotalSeconds.ToString("F2"));
//_log.Info(_outStream.Length); //_log.Info(_outStream.Length);
await Task.Delay(10); await Task.Delay(10);
}
if (cancelToken.IsCancellationRequested)
_log.Info("Song canceled");
else if (p.HasExited)
_log.Info("Song buffered completely (FFmpeg exited)");
else if (bytesRead == 0)
_log.Info("Nothing read");
if (restart)
_log.Info("Lets do some magix");
} }
if (cancelToken.IsCancellationRequested) while (restart && !cancelToken.IsCancellationRequested);
_log.Info("Song canceled");
else if (p.HasExited)
_log.Info("Song buffered completely (FFmpeg exited)");
else if (bytesRead == 0)
_log.Info("Nothing read");
} }
catch (System.ComponentModel.Win32Exception) catch (System.ComponentModel.Win32Exception)
{ {