* Fix issue #159

use timestamp for AudeioLevel observer
change smoothinterval default to 2 for more sensitive
This commit is contained in:
cnderrauber
2021-11-16 21:59:15 +08:00
committed by GitHub
parent 95e29d3766
commit c4c93eaad6
5 changed files with 29 additions and 27 deletions
+1 -1
View File
@@ -146,7 +146,7 @@ func NewConfig(confString string, c *cli.Context) (*Config, error) {
ActiveLevel: 30, // -30dBov = 0.03
MinPercentile: 40,
UpdateInterval: 500,
SmoothIntervals: 4,
SmoothIntervals: 2,
},
Redis: RedisConfig{},
Room: RoomConfig{
+19 -20
View File
@@ -6,8 +6,8 @@ import (
)
const (
// number of audio frames for observe window
observeFrames = 25 // webrtc default opus frame size 20ms, 25*20=500ms matching default UpdateInterval
// duration of audio frames for observe window
observeDuration = 500 // ms
silentAudioLevel = 127
)
@@ -15,49 +15,48 @@ const (
type AudioLevel struct {
levelThreshold uint8
currentLevel uint32
// min frames to be considered active
minActiveFrames uint32
// min duration to be considered active
minActiveDuration uint32
// for Observe goroutine use
// keeps track of current activity
observeLevel uint8
activeFrames uint32
numFrames uint32
observeLevel uint8
activeDuration uint32 // ms
observedDuration uint32 // ms
}
func NewAudioLevel(activeLevel uint8, minPercentile uint8) *AudioLevel {
l := &AudioLevel{
levelThreshold: activeLevel,
minActiveFrames: uint32(minPercentile) * observeFrames / 100,
currentLevel: silentAudioLevel,
observeLevel: silentAudioLevel,
levelThreshold: activeLevel,
minActiveDuration: uint32(minPercentile) * observeDuration / 100,
currentLevel: silentAudioLevel,
observeLevel: silentAudioLevel,
}
return l
}
// Observes a new frame, must be called from the same thread
func (l *AudioLevel) Observe(level uint8) {
l.numFrames++
func (l *AudioLevel) Observe(level uint8, durationMs uint32) {
l.observedDuration += durationMs
if level <= l.levelThreshold {
l.activeFrames++
l.activeDuration += durationMs
if l.observeLevel > level {
l.observeLevel = level
}
}
if l.numFrames >= observeFrames {
if l.observedDuration >= observeDuration {
// compute and reset
if l.activeFrames >= l.minActiveFrames {
const invObserveFrames = 1.0 / observeFrames
level := uint32(l.observeLevel) - uint32(20*math.Log10(float64(l.activeFrames)*invObserveFrames))
if l.activeDuration >= l.minActiveDuration {
level := uint32(l.observeLevel) - uint32(20*math.Log10(float64(l.activeDuration)/float64(observeDuration)))
atomic.StoreUint32(&l.currentLevel, level)
} else {
atomic.StoreUint32(&l.currentLevel, silentAudioLevel)
}
l.observeLevel = silentAudioLevel
l.activeFrames = 0
l.numFrames = 0
l.activeDuration = 0
l.observedDuration = 0
}
}
+1 -1
View File
@@ -60,6 +60,6 @@ func TestAudioLevel(t *testing.T) {
func observeSamples(a *rtc.AudioLevel, level uint8, count int) {
for i := 0; i < count; i++ {
a.Observe(level)
a.Observe(level, 20)
}
}
+2 -2
View File
@@ -344,8 +344,8 @@ func (t *MediaTrack) AddReceiver(receiver *webrtc.RTPReceiver, track *webrtc.Tra
if t.Kind() == livekit.TrackType_AUDIO {
t.audioLevel = NewAudioLevel(t.params.AudioConfig.ActiveLevel, t.params.AudioConfig.MinPercentile)
buff.OnAudioLevel(func(level uint8) {
t.audioLevel.Observe(level)
buff.OnAudioLevel(func(level uint8, duration uint32) {
t.audioLevel.Observe(level, duration)
})
} else if t.Kind() == livekit.TrackType_VIDEO {
if twcc != nil {
+6 -3
View File
@@ -88,7 +88,7 @@ type Buffer struct {
// callbacks
onClose func()
onAudioLevel func(level uint8)
onAudioLevel func(level uint8, durationMs uint32)
feedbackCB func([]rtcp.Packet)
feedbackTWCC func(sn uint16, timeNS int64, marker bool)
@@ -386,7 +386,10 @@ func (b *Buffer) calc(pkt []byte, arrivalTime int64) {
if e := p.GetExtension(b.audioExt); e != nil && b.onAudioLevel != nil {
ext := rtp.AudioLevelExtension{}
if err := ext.Unmarshal(e); err == nil {
b.onAudioLevel(ext.Level)
duration := (int64(p.Timestamp) - int64(latestTimestamp)) * 1e3 / int64(b.clockRate)
if duration > 0 {
b.onAudioLevel(ext.Level, uint32(duration))
}
}
}
}
@@ -607,7 +610,7 @@ func (b *Buffer) OnFeedback(fn func(fb []rtcp.Packet)) {
b.feedbackCB = fn
}
func (b *Buffer) OnAudioLevel(fn func(level uint8)) {
func (b *Buffer) OnAudioLevel(fn func(level uint8, durationMs uint32)) {
b.onAudioLevel = fn
}