obsproject / obsproject/obs-studio

Audio crackle (xrun) in stream and recording

Open
#11,083 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
76.4k
Forks
10.2k
Avg merge
4d 23h
Merged PRs (30d)
12

Description

Operating System Info

Other

Other OS

Ubuntu 24.04

OBS Studio Version

30.2.2

OBS Studio Version (Other)

No response

OBS Studio Log URL

https://obsproject.com/logs/uFQRTBBLSFg1hjPW

OBS Studio Crash Log URL

No response

Expected Behavior

There should be no difference in audio streams.

Current Behavior

Audio crackle in a single stream (GameSink).

Steps to Reproduce
  1. Start a recording
  2. Play a game
  3. Stop a recording
  4. Listen to the audio
Anything else we should know?

My guildies have been complaining about my game audio being a complete mess, I've been trying to find the cause for the problem over the past weeks and it is driving me nuts!

I have multiple audio streams, they are all taken from virtual sinks I have setup in pipewire and one of them (GameSink) has issues inside OBS only.

I can monitor the audio in OBS and there is no problem, you do not see it in the VU meter and it usually doesn't show up in recordings but it can... while on my stream the audio sounds like xruns (buffer underruns) ALL the time.

Finally I have found a probable cause, I noticed OBS not showing any of its input links in Carla which it normally does so I switched from PulseAudio (obs default) to a Jack sink and so far -fingers crossed- it hasn't crackled a single time!

I have setup PipeWire virtual sinks:

context.modules = [
   { name = libpipewire-module-loopback
     args = {
        node.description = "MicSolo"
        capture.props = {
           node.name = "MicSolo_capture"
           media.class = "Audio/Sink"
           audio.position = [ MONO ]
        }
        playback.props = {
           node.name = "MicSolo_playback"
           media.class = "Audio/Source"
           audio.position = [ MONO ]
        }
     }
   }
   { name = libpipewire-module-loopback
     args = {
        node.description = "MicVoice"
        capture.props = {
           node.name = "MicVoice_capture"
           media.class = "Audio/Sink"
           audio.position = [ MONO ]
        }
        playback.props = {
           node.name = "MicVoice_playback"
           media.class = "Audio/Source"
           audio.position = [ MONO ]
        }
     }
   }
   { name = libpipewire-module-loopback
     args = {
        node.description = "SideChainMusic"
        capture.props = {
           node.name = "SideChainMusic_capture"
           media.class = "Audio/Sink"
           audio.position = [ FL FR ]
        }
        playback.props = {
           node.name = "SideChainMusic_playback"
           media.class = "Audio/Source"
           audio.position = [ FL FR ]
        }
     }
   }
   { name = libpipewire-module-loopback
     args = {
        node.description = "MusicSink"
        capture.props = {
           node.name = "MusicSink_capture"
           media.class = "Audio/Sink"
           audio.position = [ FL FR ]
        }
        playback.props = {
           node.name = "MusicSink_playback"
           media.class = "Audio/Source"
           audio.position = [ FL FR ]
        }
     }
   }
   { name = libpipewire-module-loopback
     args = {
        node.description = "GameSink"
        capture.props = {
           node.name = "GameSink_capture"
           media.class = "Audio/Sink"
           audio.position = [ FL FR ]
        }
        playback.props = {
           node.name = "GameSink_playback"
           media.class = "Audio/Source"
           audio.position = [ FL FR ]
        }
     }
   }
   { name = libpipewire-module-loopback
     args = {
        node.description = "DiscordSink"
        capture.props = {
           node.name = "DiscordSink_capture"
           media.class = "Audio/Sink"
           audio.position = [ FL FR ]
        }
        playback.props = {
           node.name = "DiscordSink_playback"
           media.class = "Audio/Source"
           audio.position = [ FL FR ]
        }
     }
   }
   { name = libpipewire-module-loopback
     args = {
        node.description = "DefaultSink"
        capture.props = {
           node.name = "DefaultSink_capture"
           media.class = "Audio/Sink"
           audio.position = [ FL FR ]
        }
        playback.props = {
           node.name = "DefaultSink_playback"
           media.class = "Audio/Source"
           audio.position = [ FL FR ]
        }
     }
   }
]

I use Carla for audio processing using Jack, applications play on their respective virtual sinks and their audio goes into two mixers for audio separation between TV and headphone.

So OBS gets its game audio from the GameSink, that GameSink is also playing on my TV and my headphone so in my mind it should not crackle.

The weird thing is, it is ONLY the GameSink and NOTHING else in OBS that crackles.

At first I assumed it to be the buffer size, so I set a fixed quantum of 2048/48000 = 42.66666667ms to be on the absolute safe side...

Here is a recording with multiple audio tracks, the first track is the normal PulseAudio capture and the second is the Jack capture. As you can clearly see the first track is a complete $h17 show and the second track is perfectly fine: VIDEO

Why this happens? I have no clue, it shouldn't happen and it is especially weird that it happens to only the GameSink. Yes, I also tried deleting all the audio captures in OBS and even went to a completely stock setup... the result is always the same.

My profile settings:

[General]
Name=Kwakzalver420

[Video]
BaseCX=1920
BaseCY=1080
OutputCX=1920
OutputCY=1080
ScaleType=bilinear
ColorFormat=NV12
ColorSpace=sRGB
ColorRange=Partial
FPSCommon=60
FPSType=0
FPSInt=30
FPSNum=30
FPSDen=1
SdrWhiteLevel=300
HdrNominalPeakLevel=1000

[SimpleOutput]
VBitrate=6000
StreamEncoder=nvenc
RecEncoder=nvenc
RecQuality=Small
UseAdvanced=true
FilePath=/home/sjoer
RecFormat2=mkv
ABitrate=160
Preset=veryfast
NVENCPreset2=p5
RecRB=false
RecRBTime=20
RecRBSize=512
RecRBPrefix=Replay
StreamAudioEncoder=aac
RecAudioEncoder=aac
RecTracks=1

[Output]
Mode=Advanced
FilenameFormatting=%CCYY-%MM-%DD %hh-%mm-%ss
DelayEnable=true
DelaySec=60
DelayPreserve=true
Reconnect=true
RetryDelay=2
MaxRetries=25
BindIP=10.0.1.2
NewSocketLoopEnable=false
LowLatencyEnable=false
IPFamily=IPv4+IPv6

[AdvOut]
TrackIndex=1
RecType=Standard
RecTracks=60
FLVTrack=1
FFOutputToFile=true
FFFormat=
FFFormatMimeType=
FFVEncoderId=0
FFVEncoder=
FFAEncoderId=0
FFAEncoder=
FFAudioMixes=1
Encoder=jim_nvenc
RecRB=false
RecRBTime=600
Track3Bitrate=128
Track5Bitrate=128
Track1Name=Everything
Track2Name=VoD
Track3Name=Game
Track4Name=Voice
Track5Name=Music
Track6Name=Extra
RecFilePath=/home/sjoer/Videos/OBS Recordings
RecFormat=mkv
Rescale=true
RescaleRes=1920x1080
RecRescaleRes=1920x1080
FFRescaleRes=1920x1080
VodTrackEnabled=true
VodTrackIndex=2
RecEncoder=none
RecSplitFileType=Time
Track1Bitrate=128
Track2Bitrate=128
Track4Bitrate=128
Track6Bitrate=128
RecFormat2=mkv
ApplyServiceSettings=true
UseRescale=false
RecUseRescale=false
FFFilePath=/home/sjoer
FFVBitrate=2500
FFVGOPSize=250
FFUseRescale=false
FFIgnoreCompat=false
FFABitrate=160
RecSplitFileTime=15
RecSplitFileSize=2048
RecRBSize=512
AudioEncoder=ffmpeg_aac
RecAudioEncoder=none
RescaleFilter=3
StreamMultiTrackAudioMixes=1
FFExtension=mp4

[Audio]
MonitoringDeviceName=AT2020USB+ Pro
MonitoringDeviceId=alsa_output.usb-audio-technica_AT2020USB_-00.pro-output-0
SampleRate=48000
ChannelSetup=Stereo
MeterDecayRate=23.530000000000001
PeakMeterType=0

[Stream1]
IgnoreRecommended=false
EnableMultitrackVideo=false
MultitrackVideoMaximumAggregateBitrateAuto=true
MultitrackVideoMaximumVideoTracksAuto=true

Right now it seems to work with the Jack capture, I've got a script to automate connecting its inputs because the UI has no facility for this.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked OBS log and compare the reported PulseAudio GameSink capture with the working JACK capture, using the reproduction steps and sample recording. Done means identifying a reproducible cause for the GameSink-only xruns and confirming that the affected stream no longer crackles under the reported PipeWire setup.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, linux, ubuntu
Domain
audio-video-rtc
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.