From 865068f158b6d02e341457706ff8da725279e278 Mon Sep 17 00:00:00 2001 From: Sam Machin Date: Fri, 1 May 2026 13:43:13 +0100 Subject: [PATCH] add new CODEC_TRANSCODE option (#225) * add new CODEC_TRANSCODE option allows RTP engine to add additional codecs to the outgoing offer that wern't in the invite from Freeswitch so RTP engine will transcode outbound calls. * update README for new env var descriptions --------- Co-authored-by: Dave Horton --- README.md | 10 ++++++++++ lib/call-session.js | 10 ++++++++-- lib/utils.js | 4 ++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 07ec990..87f9c80 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,19 @@ Configuration is provided via environment variables: |JAMBONES_RTPENGINES| commans-separated list of ip:ng-port for rtpengines (e.g. '172.31.32.10:22222')|yes| |JAMBONES_TIME_SERIES_HOST| influxdb host |yes| |JAMBONES_RECORD_ALL_CALLS| enable auto record calls |no| +|JAMBONES_CODEC_OFFER_WITH_ORDER| comma-separated codec list to use as the outbound offer toward the carrier; the original codecs from the feature server are stripped first (e.g. `'opus,PCMU,PCMA,telephone-event'`) |no| +|JAMBONES_CODEC_TRANSCODE| comma-separated codec list that rtpengine should add to the outbound offer and transcode on the fly when the carrier selects them — used to support codecs the feature server does not speak (e.g. `'AMR-WB/16000'`). Requires an rtpengine build that includes the corresponding codec module. |no| +|JAMBONES_ACCEPT_AND_TRANSCODE| comma-separated codec list to accept on the outbound leg and transcode to PCMU/PCMA toward the feature server |no| +|JAMBONES_ACCEPT_G729| if set, accept G.729 on the outbound leg and transcode to PCMU/PCMA (shorthand for `JAMBONES_ACCEPT_AND_TRANSCODE=g729`) |no| |K8S| service running as kubernetes service |no| |K8S_RTPENGINE_SERVICE_NAME| rtpengine service name(required for K8S) |no| +#### Codec transcoding notes + +`JAMBONES_CODEC_OFFER_WITH_ORDER` and `JAMBONES_CODEC_TRANSCODE` can be combined. When both are set, rtpengine first strips the original codecs from the SDP, then adds the codecs listed in `JAMBONES_CODEC_OFFER_WITH_ORDER` to the offer, and finally adds the codecs from `JAMBONES_CODEC_TRANSCODE` with transcoding enabled. When only `JAMBONES_CODEC_TRANSCODE` is set, the original codecs from the feature server are kept in the offer and the transcode codecs are appended. + +Codecs that require licensed or optional rtpengine modules (AMR, AMR-WB, G.729, etc.) only work if rtpengine was compiled with support for them. Carrier-specific fmtp parameters (for example, `octet-align=1` for AMR-WB) can be appended to the codec name as needed (e.g. `AMR-WB/16000;octet-align=1`). + ### running under pm2 Typically, this application runs under [pm2](https://pm2.io) using an [ecosystem.config.js](https://pm2.keymetrics.io/docs/usage/application-declaration/) file similar to this: ```js diff --git a/lib/call-session.js b/lib/call-session.js index e864920..7c2afbf 100644 --- a/lib/call-session.js +++ b/lib/call-session.js @@ -892,8 +892,14 @@ Duration=${payload.duration} ` process.env.JAMBONES_ACCEPT_G729 ? 'g729' : ''; offerMedia = { ...offerMedia, ...(acceptCodecs && dlg.type === 'uac' && { codec: { mask: acceptCodecs, transcode: 'pcmu,pcma' } })}; - answerMedia = { ...answerMedia, ...(process.env.JAMBONES_CODEC_OFFER_WITH_ORDER && dlg.type === 'uac' && - { codec: {offer: process.env.JAMBONES_CODEC_OFFER_WITH_ORDER.split(','), strip: 'all' }})}; + answerMedia = { ...answerMedia, ...((process.env.JAMBONES_CODEC_OFFER_WITH_ORDER || + process.env.JAMBONES_CODEC_TRANSCODE) && dlg.type === 'uac' && + { codec: { + ...(process.env.JAMBONES_CODEC_OFFER_WITH_ORDER && + { offer: process.env.JAMBONES_CODEC_OFFER_WITH_ORDER.split(','), strip: 'all' }), + ...(process.env.JAMBONES_CODEC_TRANSCODE && + { transcode: process.env.JAMBONES_CODEC_TRANSCODE.split(',') }) + }})}; let opts = { ...this.rtpEngineOpts.common, ...offerMedia, diff --git a/lib/utils.js b/lib/utils.js index 8f7947c..15996b8 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -58,6 +58,10 @@ function makeRtpEngineOpts(req, srcIsUsingSrtp, dstIsUsingSrtp, padCrypto, teams offer: process.env.JAMBONES_CODEC_OFFER_WITH_ORDER.split(','), strip: 'all' }), + ...(process.env.JAMBONES_CODEC_TRANSCODE && + { + transcode: process.env.JAMBONES_CODEC_TRANSCODE.split(',') + }), }; return {