-
-
Save aperture147/ad0f5b965912537d03b0e851bb95bd38 to your computer and use it in GitHub Desktop.
package main | |
import ( | |
"bytes" | |
"io/ioutil" | |
"log" | |
"os" | |
"os/exec" | |
) | |
func check(err error) { | |
if err != nil { | |
log.Fatalln(err) | |
} | |
} | |
func main() { | |
file, err := os.Open("test.mp3") // open file | |
check(err) | |
defer file.Close() | |
buf, err := ioutil.ReadAll(file) | |
check(err) | |
cmd := exec.Command("ffmpeg", "-y", // Yes to all | |
//"-hide_banner", "-loglevel", "panic", // Hide all logs | |
"-i", "pipe:0", // take stdin as input | |
"-map_metadata", "-1", // strip out all (mostly) metadata | |
"-c:a", "libmp3lame", // use mp3 lame codec | |
"-vsync", "2", // suppress "Frame rate very high for a muxer not efficiently supporting it" | |
"-b:a", "128k", // Down sample audio birate to 128k | |
"-f", "mp3", // using mp3 muxer (IMPORTANT, output data to pipe require manual muxer selecting) | |
"pipe:1", // output to stdout | |
) | |
// resultBuffer := bytes.NewBuffer(make([]byte, 0)) // uncomment this line if you don't want to preallocate the buffer | |
resultBuffer := bytes.NewBuffer(make([]byte, 5*1024*1024)) // pre allocate 5MiB buffer | |
cmd.Stderr = os.Stderr // bind log stream to stderr | |
cmd.Stdout = resultBuffer // stdout result will be written here | |
stdin, err := cmd.StdinPipe() // Open stdin pipe | |
check(err) | |
err = cmd.Start() // Start a process on another goroutine | |
check(err) | |
_, err = stdin.Write(buf) // pump audio data to stdin pipe | |
check(err) | |
err = stdin.Close() // close the stdin, or ffmpeg will wait forever | |
check(err) | |
err = cmd.Wait() // wait until ffmpeg finish | |
check(err) | |
outputFile, err := os.Create("out.mp3") // create new file | |
check(err) | |
defer outputFile.Close() | |
_, err = outputFile.Write(resultBuffer.Bytes()) // write result buffer to file | |
check(err) | |
} |
resultBuffer := bytes.NewBuffer([]byte{})
Creating an empty buffer has one advantages and one drawback: Saves memory on creating a new mp3 file, but a long mp3 file will consume a bit of time to allocate more memory when new bytes are added to stdout pipe.
Preallocated buffer also has one advantages and one drawback: Preallocating memory will reduce the memory allocating time, but if all mp3 content doesn't fully fill the buffer, it will create a unnecessary longer and larger file (with a completely silent ending trail) which can also confuse the player.
My usecase is converting a 10-30mins of WAV/AAC file recorded from streaming station with variable bitrate from 320kbps to 120kbps (which has size of 60MiB to 200MiB) to a CBR 128k MP3 file. By monitoring, those original files could be reduced to an approx. 5MiB MP3 files.
Btw I will add a comment to resolve this issue, to inform people to choose between preallocating memory or creating it on the fly
This code works on Mac but doesn't on Linux
Got this error
[mp3 @ 0x7fc16d705780] Format mp3 detected only with low score of 1, misdetection possible!
[mp3float @ 0x7fc16d408400] Header missing
[mp3 @ 0x7fc16d705780] Could not find codec parameters for stream 0 (Audio: mp3 (mp3float), 0 channels, fltp): unspecified frame size
Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options
This code works on Mac but doesn't on Linux Got this error
[mp3 @ 0x7fc16d705780] Format mp3 detected only with low score of 1, misdetection possible! [mp3float @ 0x7fc16d408400] Header missing [mp3 @ 0x7fc16d705780] Could not find codec parameters for stream 0 (Audio: mp3 (mp3float), 0 channels, fltp): unspecified frame size Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options
Sorry, I couldn't reproduce this problem. As the log result, your file input might not be a mp3 file: Format mp3 detected only with low score of 1, misdetection possible!
This is my setup and my sample audio file, can you try my sample?
OS: Ubuntu 20.04.5 LTS x86_64
ffmpeg -version
:
ffmpeg version 4.2.7-0ubuntu0.1 Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 9 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
configuration: --prefix=/usr --extra-version=0ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
libavutil 56. 31.100 / 56. 31.100
libavcodec 58. 54.100 / 58. 54.100
libavformat 58. 29.100 / 58. 29.100
libavdevice 58. 8.100 / 58. 8.100
libavfilter 7. 57.100 / 7. 57.100
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 5.100 / 5. 5.100
libswresample 3. 5.100 / 3. 5.100
libpostproc 55. 5.100 / 55. 5.100
go version
: go version go1.18.5 linux/amd64
Sample MP3 file: Brain Damage - Pink Floyd
resultBuffer := bytes.NewBuffer([]byte{})