예제 #1
0
        private async Task BackgroundStream()
        {
            Console.WriteLine("Started background stream for " + Id);
            DataReceivedEventHandler Handler = null;
            var ProcessStartInfo             = new ProcessStartInfo
            {
                FileName              = "Includes/ffmpeg",
                UseShellExecute       = false,
                RedirectStandardInput = true,
                RedirectStandardError = true
            };

            while (!Stop.IsCancellationRequested)
            {
                try
                {
                    await WaitAdd.WaitAsync(Stop.Token);

                    Queue.Next();

                    using (Ffmpeg = new Process())
                    {
                        ProcessStartInfo.Arguments = $"-re -i \"{await Queue.StreamUrl(false)}\" -vn -content_type audio/aac -f adts ";
                        if (Queue.Playing.Type == SongType.YouTube || Queue.Playing.Type == SongType.Uploaded)
                        {
                            ProcessStartInfo.Arguments += "-c:a copy ";
                        }
                        else
                        {
                            ProcessStartInfo.Arguments += $"-c:a aac -b:a 128k -ac 2 -ar 48k ";
                        }
                        ProcessStartInfo.Arguments += $"icecast://*****:*****@localhost:80/{Id}";

                        ProcessWaiter = new TaskCompletionSource <bool>();

                        Ffmpeg.StartInfo           = ProcessStartInfo;
                        Ffmpeg.EnableRaisingEvents = true;
                        Ffmpeg.Exited += (s, e) =>
                        {
                            ProcessWaiter.TrySetResult(true);
                        };

                        Handler = async(s, e) =>
                        {
                            Console.WriteLine(e.Data ?? "");
                            if (e.Data?.StartsWith("size=") ?? false)
                            {
                                Ffmpeg.ErrorDataReceived -= Handler;
                                await Task.Delay(250).ContinueWith(delegate
                                {
                                    Chat.Home.ById(Id).Distribute(new Cloud.Json.Event
                                    {
                                        Chat = Id,
                                        Type = "start",
                                        Text = Serialize(Id)
                                    });
                                });
                            }
                        };

                        Ffmpeg.ErrorDataReceived += Handler;

                        Ffmpeg.Start();
                        Ffmpeg.BeginErrorReadLine();
                        Ffmpeg.PriorityClass = ProcessPriorityClass.BelowNormal;
                        await ProcessWaiter.Task;

                        Ffmpeg.CancelErrorRead();
                        await Ffmpeg.StandardInput.WriteAsync("q");
                    }
                }
                catch (Exception Ex)
                {
                    Console.WriteLine(Ex.ToString());
                }
                finally
                {
                    Queue.Invalidate();
                    Console.WriteLine("Stopped Playing");
                }

                if (Queue.Count == 0)
                {
                    Chat.Home.ById(Id).Distribute(new Cloud.Json.Event
                    {
                        Chat = Id,
                        Type = "start"
                    });
                }
            }
        }
예제 #2
0
        private static async Task StreamAsync(AudioOutStream Out)
        {
            var SS     = Streamer.SS.ToString(CultureInfo.InvariantCulture);
            var FFMpeg = Process.Start(new ProcessStartInfo
            {
                FileName               = "ffmpeg",
                Arguments              = $"-ss {SS} -re -i pipe:0 -f s16le -ar 48k -ac 2 -af \"{Filter.Tag}\" pipe:1",
                UseShellExecute        = false,
                RedirectStandardInput  = true,
                RedirectStandardOutput = true,
                RedirectStandardError  = true
            });

            FFMpeg.ErrorDataReceived += async(s, e) =>
            {
                var FFLog = e?.Data?.Trim();
                if (FFLog != null)
                {
                    if (FFLog.StartsWith("Duration: "))
                    {
                        TimeSpan.TryParse(FFLog.Substring(10).Split(new[] { ',' }, 2, StringSplitOptions.RemoveEmptyEntries)[0], out Duration);
                    }
                    else if (FFLog.StartsWith("size="))
                    {
                        var SplitTime = FFLog.Split(new[] { "time=" }, 2, StringSplitOptions.RemoveEmptyEntries)[1];
                        TimeSpan.TryParse(SplitTime.Split(new[] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries)[0], out Time);

                        var SpeedSplit = SplitTime.Split('=');
                        Logger.SetTitle($"Playback Speed {SpeedSplit[SpeedSplit.Length - 1].Trim()}");
                    }
                    else
                    {
                        Logger.Log($"FFMpeg | {FFLog}");
                    }

                    if (Duration != default(TimeSpan) && Time != default(TimeSpan) && (TicksRemaining = Duration.Ticks - Time.Ticks) <= 0)
                    {
                        Skip?.Cancel();
                    }
                }
            };

            FFMpeg.BeginErrorReadLine();
            BufferAsync(await GetStream(await Queue.StreamUrl()), FFMpeg.StandardInput.BaseStream, Skip.Token);

            using (var Pipe1 = FFMpeg.StandardOutput.BaseStream)
                try
                {
                    int Read = await Pipe1.ReadAsync(BuffOut, Swapper *Stride, Stride, Skip.Token);

                    while (Read != 0)
                    {
                        var Send = Out.WriteAsync(BuffOut, Swapper * Stride, Read, Skip.Token);

                        Swapper = Swapper ^ 1;
                        Read    = await Pipe1.ReadAsync(BuffOut, Swapper *Stride, Stride, Skip.Token);

                        await Send;
                    }

                    Streamer.SS = 0; //After full process without skip
                }
                catch (TaskCanceledException)
                {
                }
            catch (OperationCanceledException)
            {
            }

            Logger.Log("Disposed FFMpeg Pipe 1");
            Logger.SetTitle($"Finished Playing");

            try
            {
                FFMpeg.Kill();
            }
            catch
            {
            }
        }