mirror of
https://github.com/ossrs/srs.git
synced 2025-11-23 19:34:05 +08:00
This PR adds G.711 (PCMU/PCMA) audio codec support for WebRTC in SRS, enabling relay-only streaming of G.711 audio between WebRTC clients via WHIP/WHEP. G.711 is a widely-used, royalty-free audio codec with excellent compatibility across VoIP systems, IP cameras, and legacy telephony equipment. Fixes #4075 Many IP cameras, VoIP systems, and IoT devices use G.711 (PCMU/PCMA) as their default audio codec. Previously, SRS only supported Opus for WebRTC audio, requiring transcoding or rejecting G.711 streams entirely. This PR enables direct relay of G.711 audio streams in WebRTC, similar to how VP9/AV1 video codecs are supported. Enhanced WHIP/WHEP players with URL-based codec selection: ``` # Audio codec only http://localhost:8080/players/whip.html?acodec=pcmu http://localhost:8080/players/whip.html?acodec=pcma # Video + audio codecs http://localhost:8080/players/whip.html?vcodec=vp9&acodec=pcmu http://localhost:8080/players/whep.html?vcodec=h264&acodec=pcma # Backward compatible (codec = vcodec) http://localhost:8080/players/whip.html?codec=vp9 ``` Testing ```bash # Build and run unit tests cd trunk make utest -j && ./objs/srs_utest # Test with WHIP player # 1. Start SRS server ./objs/srs -c conf/rtc.conf # 2. Open WHIP publisher with PCMU audio http://localhost:8080/players/whip.html?acodec=pcmu # 3. Open WHEP player to receive stream http://localhost:8080/players/whep.html ``` ## Related Issues - Fixes #4075 - WebRTC G.711A Audio Codec Support - Related to #4548 - VP9 codec support (similar relay-only pattern)
186 lines
7.2 KiB
HTML
186 lines
7.2 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>SRS</title>
|
||
<meta charset="utf-8">
|
||
<style>
|
||
body{
|
||
padding-top: 30px;
|
||
}
|
||
</style>
|
||
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
|
||
<script type="text/javascript" src="js/jquery-1.12.2.min.js"></script>
|
||
<script type="text/javascript" src="js/adapter-7.4.0.min.js"></script>
|
||
<script type="text/javascript" src="js/srs.sdk.js"></script>
|
||
<script type="text/javascript" src="js/winlin.utility.js"></script>
|
||
<script type="text/javascript" src="js/srs.page.js"></script>
|
||
</head>
|
||
<body>
|
||
<img style="width: 0px; height: 0px;" src='//ossrs.net/gif/v1/sls.gif?site=ossrs.net&path=/player/rtcpublisher'/>
|
||
<div class="navbar navbar-fixed-top">
|
||
<div class="navbar-inner">
|
||
<div class="container">
|
||
<a class="brand" href="https://github.com/ossrs/srs" target="_blank">SRS</a>
|
||
<div class="nav-collapse collapse">
|
||
<ul class="nav">
|
||
<li><a id="nav_srs_player" href="srs_player.html">LivePlayer</a></li>
|
||
<!--<li><a id="nav_rtc_player" href="rtc_player.html">RTC播放器</a></li>-->
|
||
<!--<li><a id="nav_rtc_publisher" href="rtc_publisher.html">RTC推流</a></li>-->
|
||
<li><a id="nav_whip" href="whip.html">WHIP</a></li>
|
||
<li class="active"><a id="nav_whep" href="whip.html">WHEP</a></li>
|
||
<li><a href="http://ossrs.net/srs.release/releases/app.html">iOS/Andriod</a></li>
|
||
<!--<li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>-->
|
||
<!--<li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>-->
|
||
<!--<li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>-->
|
||
<!--<li><a id="nav_vlc" href="vlc.html">VLC播放器</a></li>-->
|
||
<!--<li><a id="nav_gb28181" href="srs_gb28181.html">GB28181</a></li>-->
|
||
<!--<li>
|
||
<a href="https://github.com/ossrs/srs">
|
||
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/ossrs/srs?style=social">
|
||
</a>
|
||
</li>-->
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="container">
|
||
<div id="main_info" class="alert alert-info fade in">
|
||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||
<strong><span>Usage:</span></strong> <span>Enter the WebRTC WHEP URL and click "Play" to start playing.</span>
|
||
</div>
|
||
<div class="form-inline">
|
||
URL:
|
||
<input type="text" id="txt_url" class="input-xxlarge" value="">
|
||
<button class="btn btn-primary" id="btn_play">Play</button>
|
||
<button class="btn btn-danger" id="btn_stop" disabled>Stop</button>
|
||
</div>
|
||
|
||
<p></p>
|
||
<video id="rtc_media_player" controls autoplay></video>
|
||
|
||
<p></p>
|
||
<div class="form-inline">
|
||
Controls:
|
||
<label>
|
||
<input type="checkbox" id="ch_videoonly" style="margin-bottom: 8px"> Video Only
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" id="ch_audioonly" style="margin-bottom: 8px"> Audio Only
|
||
</label>
|
||
</div>
|
||
|
||
SessionID: <span id='sessionid'></span>
|
||
|
||
<p></p>
|
||
Audio: <span id='acodecs'></span><br/>
|
||
Video: <span id='vcodecs'></span>
|
||
|
||
<p></p>
|
||
Simulator: <a href='#' id='simulator-drop'>Drop</a>
|
||
|
||
<footer>
|
||
<p></p>
|
||
<p><a href="https://github.com/ossrs/srs">SRS Team © 2020</a></p>
|
||
</footer>
|
||
</div>
|
||
<script type="text/javascript">
|
||
$(function(){
|
||
var sdk = null; // Global handler to do cleanup when republishing.
|
||
var statsTimer = null;
|
||
var startPlay = function() {
|
||
$('#rtc_media_player').show();
|
||
|
||
if (statsTimer) {
|
||
clearInterval(statsTimer);
|
||
}
|
||
|
||
// Close PC when user replay.
|
||
if (sdk) {
|
||
sdk.close();
|
||
}
|
||
sdk = new SrsRtcWhipWhepAsync();
|
||
|
||
// User should set the stream when publish is done, @see https://webrtc.org/getting-started/media-devices
|
||
// However SRS SDK provides a consist API like https://webrtc.org/getting-started/remote-streams
|
||
$('#rtc_media_player').prop('srcObject', sdk.stream);
|
||
// Optional callback, SDK will add track to stream.
|
||
// sdk.ontrack = function (event) { console.log('Got track', event); sdk.stream.addTrack(event.track); };
|
||
|
||
// https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/getStats
|
||
statsTimer = setInterval(() => {
|
||
sdk.pc.getStats(null).then((stats) => {
|
||
let audioStatsOutput = SrsRtcFormatStats(stats, 'audio');
|
||
let videoStatsOutput = SrsRtcFormatStats(stats, 'video');
|
||
|
||
document.querySelector("#acodecs").innerHTML = audioStatsOutput;
|
||
document.querySelector("#vcodecs").innerHTML = videoStatsOutput;
|
||
|
||
if (audioStatsOutput && videoStatsOutput) {
|
||
clearInterval(statsTimer);
|
||
console.log('Stats detected, stopping stats timer');
|
||
}
|
||
});
|
||
}, 1000);
|
||
|
||
// For example: webrtc://r.ossrs.net/live/livestream
|
||
var url = $("#txt_url").val();
|
||
var query = parse_query_string();
|
||
|
||
// Support codec parameters: codec (alias for vcodec), vcodec, acodec
|
||
var vcodec = query.vcodec || query.codec;
|
||
var acodec = query.acodec;
|
||
|
||
sdk.play(url, {
|
||
videoOnly: $('#ch_videoonly').prop('checked'),
|
||
audioOnly: $('#ch_audioonly').prop('checked'),
|
||
vcodec: vcodec,
|
||
acodec: acodec
|
||
}).then(function(session){
|
||
$('#sessionid').html(session.sessionid);
|
||
$('#simulator-drop').attr('href', session.simulator + '?drop=1&username=' + session.sessionid);
|
||
// Enable stop button after successful play
|
||
$('#btn_stop').prop('disabled', false);
|
||
$('#btn_play').prop('disabled', true);
|
||
}).catch(function (reason) {
|
||
sdk.close();
|
||
$('#rtc_media_player').hide();
|
||
console.error(reason);
|
||
});
|
||
};
|
||
|
||
var stopPlay = function() {
|
||
if (sdk) {
|
||
sdk.close();
|
||
|
||
if (statsTimer) {
|
||
clearInterval(statsTimer);
|
||
statsTimer = null;
|
||
}
|
||
|
||
$('#btn_stop').prop('disabled', true);
|
||
$('#btn_play').prop('disabled', false);
|
||
$('#sessionid').html('(stopped)');
|
||
$('#rtc_media_player').hide();
|
||
}
|
||
};
|
||
|
||
$('#rtc_media_player').hide();
|
||
var query = parse_query_string();
|
||
srs_init_whep("#txt_url", query);
|
||
|
||
$("#btn_play").click(startPlay);
|
||
$("#btn_stop").click(stopPlay);
|
||
// Never play util windows loaded @see https://github.com/ossrs/srs/issues/2732
|
||
if (query.autostart === 'true') {
|
||
$('#rtc_media_player').prop('muted', true);
|
||
console.warn('For autostart, we should mute it, see https://www.jianshu.com/p/c3c6944eed5a ' +
|
||
'or https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#audiovideo_elements');
|
||
window.addEventListener("load", function(){ startPlay(); });
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|
||
|