/// <summary> /// Prepares for writing. /// </summary> /// <param name="showFFmpegOutput">Show output to terminal. Error stream will not be redirected if this is set to true.</param> public void OpenWrite(bool showFFmpegOutput = false) { if (OpenedForWriting) { throw new InvalidOperationException("File was already opened for writing!"); } var cmd = $"-f rawvideo -video_size {Width}:{Height} -r {Framerate} -pixel_format rgb24 -i - " + $"-c:v {EncoderOptions.EncoderName} {EncoderOptions.EncoderArguments} -f {EncoderOptions.Format}"; if (UseFilename) { if (File.Exists(Filename)) { File.Delete(Filename); } InputDataStream = FFmpegWrapper.OpenInput(ffmpeg, $"{cmd} \"{Filename}\"", out ffmpegp, showFFmpegOutput); } else { csc = new CancellationTokenSource(); // using stream (InputDataStream, OutputDataStream) = FFmpegWrapper.Open(ffmpeg, $"{cmd} -", out ffmpegp, showFFmpegOutput); _ = OutputDataStream.CopyToAsync(DestinationStream, csc.Token); } OpenedForWriting = true; }
/// <summary> /// Opens output audio file for writing. This will delete any existing file. Call this before writing samples. /// </summary> /// <param name="showFFmpegOutput">Show output to terminal. Error stream will not be redirected if this is set to true.</param> public void OpenWrite(bool showFFmpegOutput = false) { if (OpenedForWriting) { throw new InvalidOperationException("File was already opened for writing!"); } var cmd = $"-f s{BitDepth}le -channels {Channels} -sample_rate {SampleRate} -i - " + $"-c:a {EncoderOptions.EncoderName} {EncoderOptions.EncoderArguments} -f {EncoderOptions.Format}"; if (UseFilename) { if (File.Exists(Filename)) { File.Delete(Filename); } InputDataStream = FFmpegWrapper.OpenInput(ffmpeg, $"{cmd} \"{Filename}\"", out ffmpegp, showFFmpegOutput); } else { csc = new CancellationTokenSource(); // using stream (InputDataStream, OutputDataStream) = FFmpegWrapper.Open(ffmpeg, $"{cmd} -", out ffmpegp, showFFmpegOutput); _ = OutputDataStream.CopyToAsync(DestinationStream, csc.Token); } OpenedForWriting = true; }
/// <summary> /// Opens output stream for writing and returns both the input and output streams. Make sure to use a streaming format (like flv). /// </summary> /// <param name="options">Output options</param> /// <param name="process">FFmpeg process</param> /// <param name="inputArguments">Input arguments (such as -f, -v:c, -video_size, -ac, -ar...)</param> /// <param name="showOutput">Show output to terminal. Error stream will not be redirected if this is set to true.</param> /// <param name="ffmpegExecutable">Name or path to the ffmpeg executable</param> public static (Stream Input, Stream Output) StreamToStream(EncoderOptions options, out Process process, string inputArguments = "", bool showOutput = false, string ffmpegExecutable = "ffmpeg") { var(input, output) = FFmpegWrapper.Open(ffmpegExecutable, $"{inputArguments} -i - " + $"-c:v {options.EncoderName} {options.EncoderArguments} -f {options.Format} -", out process, showOutput); return(input, output); }
/// <summary> /// Prepares for writing. /// </summary> /// <param name="showFFmpegOutput">Show output to terminal. Error stream will not be redirected if this is set to true.</param> /// <param name="thread_queue_size">Max. number of queued packets when reading from file/stream. /// Should be set to higher when dealing with high rate/low latency streams.</param> public void OpenWrite(bool showFFmpegOutput = false, int thread_queue_size = 4096) { if (OpenedForWriting) { throw new InvalidOperationException("File/Stream was already opened for writing!"); } var manual = new ManualResetEvent(false); socket = new Socket(SocketType.Stream, ProtocolType.Tcp); socket.Bind(new IPEndPoint(IPAddress.Loopback, 0)); socket.Listen(4); var port = ((IPEndPoint)socket.LocalEndPoint).Port; socket.BeginAccept(r => { connected_socket = socket.EndAccept(r); InputDataStreamAudio = new NetworkStream(connected_socket); manual.Set(); }, null); var cmd = $"-f s{AudioBitDepth}le -channels {AudioChannels} -sample_rate {AudioSampleRate} " + $"-thread_queue_size {thread_queue_size} -i \"tcp://{IPAddress.Loopback}:{port}\" " + $"-f rawvideo -video_size {VideoWidth}:{VideoHeight} -r {VideoFramerate} " + $"-thread_queue_size {thread_queue_size} -pixel_format rgb24 -i - " + $"-map 0 -c:a {AudioEncoderOptions.EncoderName} {AudioEncoderOptions.EncoderArguments} " + $"-map 1 -c:v {VideoEncoderOptions.EncoderName} {VideoEncoderOptions.EncoderArguments} " + $"-f {VideoEncoderOptions.Format}"; if (UseFilename) { if (File.Exists(Filename)) { File.Delete(Filename); } InputDataStreamVideo = FFmpegWrapper.OpenInput(ffmpeg, $"{cmd} \"{Filename}\"", out ffmpegp, showFFmpegOutput); } else { csc = new CancellationTokenSource(); // using stream (InputDataStreamVideo, OutputDataStream) = FFmpegWrapper.Open(ffmpeg, $"{cmd} -", out ffmpegp, showFFmpegOutput); _ = OutputDataStream.CopyToAsync(DestinationStream, csc.Token); } manual.WaitOne(); OpenedForWriting = true; }