Last active
December 20, 2019 11:49
-
-
Save chgeuer/92ee4798be7f1c640ebd3fd4ac1c04ba to your computer and use it in GitHub Desktop.
Ogg2Wav
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.microsoft.cse; | |
import java.io.*; | |
import java.nio.file.*; | |
public class Main { | |
private static class Pump implements Runnable { | |
private final InputStream is; | |
private final OutputStream os; | |
Pump(InputStream is, OutputStream os) { | |
this.is = is; | |
this.os = os; | |
} | |
@Override | |
public void run() { | |
byte buffer[] = new byte[1024 * 1024]; | |
int numRead; | |
try { | |
while ((numRead = this.is.read(buffer)) != -1) { | |
os.write(buffer, 0, numRead); | |
} | |
this.os.close(); | |
} catch (IOException ioe) { | |
System.err.println(ioe.getMessage()); | |
} | |
} | |
public static Thread start(InputStream is, OutputStream os) { | |
var t = new Thread(new Pump(is, os)); | |
t.start(); | |
return t; | |
} | |
}; | |
public static void main(String[] args) throws Exception { | |
String sourceFileName = "C:\\Users\\chgeuer\\Music\\malte\\long-test.ogg"; | |
String outputFile = "C:\\Users\\chgeuer\\Music\\malte\\testing.wav"; | |
File inputFile = new File(sourceFileName); | |
byte[] fileContent = Files.readAllBytes(inputFile.toPath()); | |
Process process = Runtime.getRuntime().exec( | |
"ffmpeg.exe -i - -f wav -flags +bitexact -c:a pcm_s16le -ar 16000 -ac 1 -"); | |
InputStream oggStream = new ByteArrayInputStream(fileContent); | |
OutputStream processStdinStream = process.getOutputStream(); | |
Thread threadIn = Pump.start(oggStream, processStdinStream); | |
InputStream processStdoutStream = process.getInputStream(); | |
ByteArrayOutputStream wavStream = new ByteArrayOutputStream(); | |
Thread threadOut = Pump.start(processStdoutStream, wavStream); | |
InputStream processStderrStream = process.getErrorStream(); | |
ByteArrayOutputStream loggingStream = new ByteArrayOutputStream(); | |
Thread threadErr = Pump.start(processStderrStream, loggingStream); | |
threadIn.join(); | |
int exitCode = process.waitFor(); | |
threadOut.join(); | |
threadErr.join(); | |
try(var outPutFileStream = new FileOutputStream(new File(outputFile))) { | |
byte[] wavByteArray = wavStream.toByteArray(); | |
long l1 = wavByteArray.length - 8; | |
wavByteArray[4] = (byte) ((l1 >> 0) & 0xff); | |
wavByteArray[5] = (byte) ((l1 >> 8) & 0xff); | |
wavByteArray[6] = (byte) ((l1 >> 16) & 0xff); | |
wavByteArray[7] = (byte) ((l1 >> 24) & 0xff); | |
long l2 = wavByteArray.length - 78; | |
wavByteArray[0x4a] = (byte) ((l2 >> 0) & 0xff); | |
wavByteArray[0x4b] = (byte) ((l2 >> 8) & 0xff); | |
wavByteArray[0x4c] = (byte) ((l2 >> 16) & 0xff); | |
wavByteArray[0x4d] = (byte) ((l2 >> 24) & 0xff); | |
outPutFileStream.write(wavByteArray); | |
} | |
System.out.println("Exit Code: " + exitCode); | |
System.out.println(new String(loggingStream.toByteArray())); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace lib | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.IO; | |
using System.Threading.Tasks; | |
public static class ProcessExtensions | |
{ | |
public class ProcessResult | |
{ | |
public byte[] Stdout { get; set; } | |
public byte[] Stderr { get; set; } | |
public int? ExitCode { get; set; } | |
} | |
public static Task<ProcessResult> RunAsync(string filename, string arguments, Stream stdinStream) | |
{ | |
var processStartInfo = new ProcessStartInfo | |
{ | |
FileName = filename, | |
Arguments = arguments, | |
RedirectStandardInput = stdinStream != null && stdinStream.CanRead, | |
RedirectStandardOutput = true, | |
RedirectStandardError = true, | |
UseShellExecute = false, | |
CreateNoWindow = true | |
}; | |
return processStartInfo.RunAsync(stdinStream); | |
} | |
public static Task<ProcessResult> RunAsync(this ProcessStartInfo startInfo, Stream stdinStream) => | |
startInfo.RunAsync(TimeSpan.Zero, stdinStream); | |
public static async Task<ProcessResult> RunAsync(this ProcessStartInfo startInfo, TimeSpan timeout, Stream stdinStream) | |
{ | |
using var stdout = new MemoryStream(); | |
using var stderr = new MemoryStream(); | |
using var process = new Process | |
{ | |
StartInfo = startInfo, | |
EnableRaisingEvents = true | |
}; | |
var tasks = new List<Task>(); | |
var processExitEvent = new TaskCompletionSource<bool>(); | |
tasks.Add(processExitEvent.Task); | |
process.Exited += (sender, args) => { Task.Run(() => { processExitEvent.TrySetResult(true); }); }; | |
var startSuccess = process.Start(); | |
if (!startSuccess) | |
{ | |
return new ProcessResult { Stdout = stdout.ToArray(), Stderr = stderr.ToArray(), ExitCode = process.ExitCode }; | |
} | |
if (process.StartInfo.RedirectStandardInput && stdinStream != null && stdinStream.CanRead) | |
{ | |
tasks.Add(stdinStream.CopyToAndCloseAsync(process.StandardInput.BaseStream)); | |
} | |
if (process.StartInfo.RedirectStandardOutput) | |
{ | |
tasks.Add(process.StandardOutput.BaseStream.CopyToAndCloseAsync(stdout)); | |
} | |
if (process.StartInfo.RedirectStandardError) | |
{ | |
tasks.Add(process.StandardError.BaseStream.CopyToAndCloseAsync(stderr)); | |
} | |
var processCompletionTask = Task.WhenAll(tasks); | |
Task<Task> awaitingTask = (timeout > TimeSpan.Zero) | |
? Task.WhenAny(processCompletionTask, Task.Delay(timeout)) | |
: Task.WhenAny(processCompletionTask); | |
var finishedTask = await awaitingTask; | |
if (finishedTask == processCompletionTask) | |
{ | |
return new ProcessResult { Stdout = stdout.ToArray(), Stderr = stderr.ToArray(), ExitCode = process.ExitCode }; | |
} | |
else | |
{ | |
try { process.Kill(); } catch { } | |
return new ProcessResult { Stdout = stdout.ToArray(), Stderr = stderr.ToArray(), ExitCode = null }; | |
} | |
} | |
private static async Task CopyToAndCloseAsync(this Stream from, Stream to) | |
{ | |
await from.CopyToAsync(to); | |
to.Close(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment