-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wav.encode on mixer creates file of about 50G in just seconds #148
Comments
Hey 👋 The current behaviour of |
@MarkKremer I am trying to capture the complete audio and stream it to the RTMP link. Is there any way I can achieve this without changing the code that plays sound using mixer? |
I think it would be very hacky. What package are you using? |
I was thinking about adding a "don't play silence" option to the mixer but I don't want to add it just to work around another package... |
https://github.com/ikemen-engine/Ikemen-GO/blob/develop/src/sound.go#L494 I want to stream this audio. |
Can you please point me to the code where I can add this flag to not to stream silence? |
I happen to have a POC here. However, I think another problem (and the cause of why it fills up your file so quickly) is that the encoder consumes the streamer as quick as it can write it to the file. The speaker reads from the stream much more slowly. Given the repo you linked, I'm also thinking you may actually want to continue playing silence in between sounds. That no streams are added to the mixer doesn't necessarily mean the game has stopped... Do you want to write to the file while also playing it through the speaker still or do you need it to just play to the file or the speaker but not both? |
I only need the sound to be written to file, not both. Yes, you're right about the encoder quickly writing the streams and then streaming silence. I want the writer to write the sound to the file exactly as it was played in the game or through the speaker. |
A set-up that could work:
The throttler doesn't exist yet but would throttle the consumption to a given sample rate. The I've made a quick POC of what the set-up including the throttle node could look like: package main
import (
"os"
"time"
"github.com/gopxl/beep"
"github.com/gopxl/beep/mp3"
"github.com/gopxl/beep/wav"
)
func main() {
in := "input-file.mp3"
out := "output-file.wav"
inFile, err := os.Open(in)
if err != nil {
panic(err)
}
source, format, err := mp3.Decode(inFile)
if err != nil {
panic(err)
}
mixer := &beep.Mixer{}
mixer.Add(source)
throttle := Throttle(mixer, format.SampleRate.N(time.Second), time.Second/30)
ctrl := &beep.Ctrl{
Streamer: throttle,
}
// Simulate the game stopping after 5 seconds.
go func() {
time.Sleep(time.Second * 5)
ctrl.Streamer = nil
}()
outFile, err := os.OpenFile(out, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
panic(err)
}
err = wav.Encode(outFile, ctrl, format)
if err != nil {
panic(err)
}
}
func Throttle(streamer beep.Streamer, sampleRate int, debounce time.Duration) beep.Streamer {
return &Throttler{
streamer: streamer,
sampleRate: sampleRate,
debounce: debounce,
samplesConsumed: 0,
startTime: time.Now(),
}
}
type Throttler struct {
streamer beep.Streamer
sampleRate int
debounce time.Duration
startTime time.Time
samplesConsumed int
}
func (t *Throttler) Stream(samples [][2]float64) (n int, ok bool) {
for {
millisecondsElapsed := time.Now().Sub(t.startTime) / time.Millisecond // work with milliseconds instead of seconds to avoid too large rounding errors.
maxConsumption := int(millisecondsElapsed) * t.sampleRate / 1000
if maxConsumption > t.samplesConsumed {
break
}
time.Sleep(t.debounce)
}
n, ok = t.streamer.Stream(samples)
t.samplesConsumed += n
return
}
func (t *Throttler) Err() error {
return nil
}
Like I said, this is a quick POC. Please let me know if you run into any problems. This could be a good addition to the Beep package. I may refine it and add it to the package once I have more time. I have quite the busy schedule right now. :) Edit: after you signal that the writing must stop with the |
Hi @MarkKremer Just a doubt, how changing this debounce will affect the recodring.
Let me know if I can help you with implementing this feature in beep 😃 |
tldr: higher debounce is more latency between changes to the Mixer and the changes showing up in the stream. But might be more efficient. The debounce is the difference between:
and
Say you want to add a streamer to the The reason I added the debounce is because I suspected it may be more efficient to process a bunch of samples at once and wait for a little more compared to processing a little amount of samples and switching between goroutines more. However, I haven't checked that assumption, so it would be good to test that in the near future. Maybe Go is more efficient when switching? Feel free to have a try at calculating the exact amount of waiting time instead of having a configurable debounce. Otherwise I'll have a try when I feel like it between the other things I'm doing. :) A debounce of 1/30th a second it not that noticeable, but it would be nice to drop the argument so users don't have to think about it. Like the speaker, |
Hi
I am trying to save the sound to a file that is being played using the mixer. But the WAV file created is way big. Can any anyone please help me with this?
Any help is appreciated
The text was updated successfully, but these errors were encountered: