mirror of
https://github.com/jambonz/sbc-outbound.git
synced 2025-12-18 20:17:46 +00:00
when far end answers with only pcma, passthrough instead of transcoding to pcmu (#208)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -36,3 +36,4 @@ node_modules
|
||||
.DS_Store
|
||||
|
||||
examples/*
|
||||
CLAUDE.md
|
||||
@@ -9,7 +9,8 @@ const {
|
||||
makeFullMediaReleaseKey,
|
||||
makePartnerFullMediaReleaseKey,
|
||||
isValidDomainOrIP,
|
||||
removeVideoSdp
|
||||
removeVideoSdp,
|
||||
determineAnswerCodec
|
||||
} = require('./utils');
|
||||
const { MediaPath } = require('./constants.json');
|
||||
const {forwardInDialogRequests} = require('drachtio-fn-b2b-sugar');
|
||||
@@ -99,8 +100,9 @@ const updateRtpEngineFlags = (sdp, opts) => {
|
||||
try {
|
||||
const parsed = sdpTransform.parse(sdp);
|
||||
const codec = parsed.media[0].rtp[0].codec;
|
||||
// Only add telephone-event support, don't restrict to specific G.711 codec yet
|
||||
// This allows far end to choose between PCMU/PCMA freely
|
||||
if (['PCMU', 'PCMA'].includes(codec)) {
|
||||
opts.flags.push(`codec-accept-${codec}`);
|
||||
opts.flags.push('codec-accept-telephone-event');
|
||||
}
|
||||
} catch {}
|
||||
@@ -554,12 +556,16 @@ class CallSession extends Emitter {
|
||||
localSdpB: response.sdp,
|
||||
localSdpA: async(sdp, res) => {
|
||||
this.rtpEngineOpts.uac.tag = res.getParsedHeader('To').params.tag;
|
||||
|
||||
// Determine which codec to use based on far end negotiation
|
||||
const {codec} = determineAnswerCodec(sdp, this.req.body, this.logger);
|
||||
|
||||
const opts = {
|
||||
...this.rtpEngineOpts.common,
|
||||
...this.rtpEngineOpts.uas.mediaOpts,
|
||||
'from-tag': this.rtpEngineOpts.uas.tag,
|
||||
'to-tag': this.rtpEngineOpts.uac.tag,
|
||||
flags: ['single codec', 'inject DTMF'],
|
||||
flags: ['single codec', 'inject DTMF', `codec-accept-${codec}`, 'codec-accept-telephone-event'],
|
||||
sdp
|
||||
};
|
||||
const response = await this.answer(opts);
|
||||
|
||||
52
lib/utils.js
52
lib/utils.js
@@ -349,6 +349,55 @@ const removeVideoSdp = (sdp) => {
|
||||
parsedSdp.media = parsedSdp.media.filter((media) => media.type !== 'video');
|
||||
return sdpTransform.write(parsedSdp);
|
||||
};
|
||||
|
||||
const determineAnswerCodec = (farEndSdp, featureServerSdp, logger) => {
|
||||
try {
|
||||
// Parse both SDPs
|
||||
const farEndParsed = sdpTransform.parse(farEndSdp);
|
||||
const fsParsed = sdpTransform.parse(featureServerSdp);
|
||||
|
||||
// Get negotiated codec from far end (first codec in answer)
|
||||
const negotiatedCodec = farEndParsed.media[0].rtp[0].codec;
|
||||
|
||||
// Get all codecs offered by feature server
|
||||
const fsCodecs = fsParsed.media[0].rtp.map((r) => r.codec);
|
||||
|
||||
logger.debug({negotiatedCodec, fsCodecs}, 'determineAnswerCodec: analyzing codec negotiation');
|
||||
|
||||
// If far end negotiated G.711 (PCMU/PCMA) AND it was in the FS offer, pass it through
|
||||
if (['PCMU', 'PCMA'].includes(negotiatedCodec) && fsCodecs.includes(negotiatedCodec)) {
|
||||
logger.info({negotiatedCodec}, 'G.711 codec passthrough - no transcoding needed');
|
||||
return {
|
||||
codec: negotiatedCodec,
|
||||
needsTranscoding: false
|
||||
};
|
||||
}
|
||||
|
||||
// Otherwise, we need to transcode to first G.711 codec in FS offer
|
||||
const firstG711 = fsCodecs.find((c) => ['PCMU', 'PCMA'].includes(c));
|
||||
if (firstG711) {
|
||||
logger.info({negotiatedCodec, transcodeTarget: firstG711}, 'Transcoding required to G.711');
|
||||
return {
|
||||
codec: firstG711,
|
||||
needsTranscoding: true
|
||||
};
|
||||
}
|
||||
|
||||
// Fallback: use PCMU
|
||||
logger.info({negotiatedCodec}, 'No G.711 in FS offer, defaulting to PCMU');
|
||||
return {
|
||||
codec: 'PCMU',
|
||||
needsTranscoding: true
|
||||
};
|
||||
} catch (err) {
|
||||
logger.error({err}, 'Error determining answer codec, defaulting to PCMU');
|
||||
return {
|
||||
codec: 'PCMU',
|
||||
needsTranscoding: true
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
makeRtpEngineOpts,
|
||||
selectHostPort,
|
||||
@@ -364,5 +413,6 @@ module.exports = {
|
||||
makeFullMediaReleaseKey,
|
||||
makePartnerFullMediaReleaseKey,
|
||||
isValidDomainOrIP,
|
||||
removeVideoSdp
|
||||
removeVideoSdp,
|
||||
determineAnswerCodec
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user