Feature Description
This document describes the features that AudioMixerPlugin
can implement.
- Feature 1: it can play back the background music in TRTC. Click here to try out the audio mixing demo.
- Feature 2: it can capture the sound of both the mic and system/tab at the same time.
Feature 1. Playing back Background Music in TRTC Call
Supported platforms
OS | Browser Type | Lowest Version Required | Increasing Background Music Volume | Setting Volume | Setting Playback Rate | Setting Playback Position | Multiple Replacements After Adding Music To Audio Track |
---|---|---|---|---|---|---|---|
macOS | Chrome (desktop) | 56+ | ✔ | ✔ | ✔ | ✔ | ✔ |
macOS | Safari (desktop) | 11+ | ✔ | ✖ | ✖ | ✖ | ✖ |
macOS | Firefox (desktop) | 56+ | ✔ | ✔ | ✖ | ✔ | ✔ |
macOS | Edge (desktop) | 80+ | ✔ | ✔ | ✔ | ✔ | ✔ |
Windows | Chrome (desktop) | 56+ | ✔ | ✔ | ✔ | ✔ | ✔ |
Windows | QQ Browser in ultrafast mode (desktop) | 10.4+ | ✔ | ✔ | ✔ | ✔ | ✔ |
Windows | Firefox (desktop) | 56+ | ✔ | ✔ | ✖ | ✔ | ✔ |
Windows | Edge (desktop) | 80+ | ✔ | ✔ | ✔ | ✔ | ✔ |
iOS | Safari (mobile) | 14+ | ✔ | ✖ | ✖ | ✖ | ✖ |
iOS | WeChat embedded browser | ✖ | |||||
Android | Chrome (mobile) | 81+ | ✔ | ✔ | ✔ | ✔ | ✔ |
Android | WeChat embedded browser (TBS kernel) | ✔ | ✔ | ✔ | ✔ | ✔ | ✖ |
Android | QQ Browser (mobile) | ✖ |
Step 1. Create a music instance
Install the RTCAudioMixer in the project.
npm install rtc-audio-mixer
The AudioMixerPlugin
plugin needs to be imported together with TRTC
in the same scope.
import TRTC from 'trtc-js-sdk';
import AudioMixerPlugin from 'rtc-audio-mixer';
Call the AudioMixerPlugin.createAudioSource(params)
method to create an AudioSource
music instance with the
following parameters:
url
: it is the music file address, which is required and ofString
type. You can use an online file address or use a blob URL generated by the object selected from the local system.loop
: it indicates whether to loop the music, which is optional and ofBoolean
type. The default value isfalse
, indicating not to loop.volume
: it is the volume, which is optional and ofNumber
type. The value range is 0–1, and the default value is 1.
// You can use an online file address or use a blob URL generated by a local file to load. For more information, please see the API overview at the end of this document.
let audioSourceA = AudioMixerPlugin.createAudioSource({url: 'https://audioSourceA.mp3'});
Notes
- When an online sound effect file is played back, it must support
CORS
, and the access protocol must behttps
. - Supported formats include MP3, AAC, and other audio formats supported by the used browser.
- When there is no user interaction on the webpage, the browser will block the playback of any medias with sound on the webpage. We recommend you prompt the user to click on the webpage first before performing relevant operations. For more information, please see Autoplay_guide.
Step 2. Publish mixed audio stream
Call the AudioMixerPlugin.mix(params)
method to get mixedAudioTrack
with background music added, which can replace
the audio track in the stream to be published.
targetTrack
: audio track to which background music to be added. This parameter is optional. If it is empty, a track containing only the background music will be generated.sourceList
: music instance created in step 1, which is required and ofArray
type, such as[ audioSourceA, audioSourceB ]
.
Scenario 1. Replace before release
Before publishing localStream
, replace the audio track in localStream
with mixedAudioTrack
.
let audioSourceA = AudioMixerPlugin.createAudioSource({url: 'https://audioSourceA.mp3'});
let audioSourceB = AudioMixerPlugin.createAudioSource({url: 'https://audioSourceB.mp3'});
const localStream = TRTC.createStream({userId: 'user', audio: true, video: true});
await localStream.initialize();
// 1. Get the mic track
let originAudioTrack = localStream.getAudioTrack();
// 2. Mix it with `audioSourceA` and `audioSourceB` to generate `mixedAudioTrack`
mixedAudioTrack = await AudioMixerPlugin.mix({targetTrack: originAudioTrack, sourceList: [audioSourceA, audioSourceB]});
// 3. Replace the mic track
await localStream.replaceTrack(mixedAudioTrack);
// 4. Publish
client.publish(localStream);
// 5. Call the `play` method to play back the track, and both parties in the call can hear the background music
audioSourceA.play();
Scenario 2. Replacing after publish
let audioSourceA = AudioMixerPlugin.createAudioSource({url: 'https://audioSourceA.mp3'});
let audioSourceB = AudioMixerPlugin.createAudioSource({url: 'https://audioSourceB.mp3'});
// 1. Get the mic track
let originAudioTrack = localStream.getAudioTrack();
// 2. Mix the mic track with `audioSourceA` and `audioSourceB`
mixedAudioTrack = await AudioMixerPlugin.mix({targetTrack: originAudioTrack, sourceList: [audioSourceA, audioSourceB]});
// 3. Replace the audio track in `localStream`
await localStream.replaceTrack(mixedAudioTrack);
// 4. Call the `play` method to play back the track, and both parties in the call can hear the background music
audioSourceA.play();
audioSourceB.play();
Scenario 3. Mute mic and play back background music
let audioSourceA = AudioMixerPlugin.createAudioSource({url: 'https://audioSourceA.mp3'});
let audioSourceB = AudioMixerPlugin.createAudioSource({url: 'https://audioSourceB.mp3'});
// It temporarily stores the track containing the mic sound and background music, which can be used to unmute the mic
let microAndBgmTrack = localStream.getAudioTrack();
// 1. Generate the background music containing only `audioSourceA` and `audioSourceB`
let bgmTrack = await AudioMixerPlugin.mix({sourceList: [audioSourceA, audioSourceB]});
// 2. Replace the audio track in `localStream`. At this point, only the background music exists, and mic sound does not exist
await localStream.replaceTrack(bgmTrack);
// If you want to unmute the mic and retain the background music, you can simply restore the track containing the mic sound and background music
localStream.replaceTrack(microAndBgmTrack);
Feature 2. Capturing the Sound of Both Mic and System/Tab at the Same Time
Supported platforms
The system sound can be captured only with Chrome 74+. On Windows and Chrome OS, the sound of the entire system can be captured. On Linux and macOS, only the sound of the active tab can be captured.
Step1. Create a video stream for screen sharing and an audio stream containing only the mic sound
// The `AudioMixerPlugin` plugin needs to be imported together with `TRTC` in the same scope.
import TRTC from 'trtc-js-sdk';
import AudioMixerPlugin from 'rtc-audio-mixer';
Capture the screen sharing stream and the mic audio stream.
// Create a screen sharing stream
const screenStream = TRTC.createStream({
screenAudio: true,
screen: true,
...
});
// Create a mic audio stream
const localStream = TRTC.createStream({
audio: false,
video: true,
...
});
await screenStream.initialize();
await localStream.initialize();
Step 2. Mix the system audio track with the mic audio track and publish the mixed track
const screenAudioTrack = screenStream.getAudioTrack();
const microphoneTrack = localStream.getAudioTrack();
// Mix the system audio track with the mic audio track
const mixedTrack = await AudioMixerPlugin.mix({targetTrack: microphoneTrack, trackList: [screenAudioTrack]});
// Replace the audio track in `screenStream`
await screenStream.replaceTrack(mixedTrack);
// Publish the stream
await client.publish(screenStream);
Feature 3: Frequent change of music in the mix
If you need to update the background music frequently during the call, you can refer to the following code snippet.
// Create a custom audioElement
let audioElementA = document.createElement('audio');
audioElementA.src = 'music-001.mp3'; // use a format supported by the browser
audioElementA.load();
audioElementA.play(); // call the play method when you need to play background music
// createAudioSourceFromElement(HTMLAudioElement) can pass in an AudioElement that you created yourself, or an AudioElement that you get from the page using getElementById
let audioSourceA = AudioMixerPlugin.createAudioSourceFromElement(audioElementA);
// Add background music
let originAudioTrack = localStream.getAudioTrack();
mixedAudioTrack = await AudioMixerPlugin.mix({targetTrack: originAudioTrack, sourceList: [audioSourceA]});
await localStream.replaceTrack(mixedAudioTrack);
audioSourceA.play();
// Update music url
audioElementA.src = 'music-002.mp3';
audioElementA.load();
audioElementA.play();
Feature 4: Release resources
await client.unpublish(localStream); // unpush the stream
await client.leave(); // check out
// Destroy the generated mixedAudioTrack, and the previously referenced audio resource
AudioMixerPlugin.destroySource(mixedAudioTrack);
// If you don't need to use it you can
audioSourceA.destroy();
audioSourceB.destroy();
If you are using a custom AudioElement, you can use the following code to release the resource.
audioElement.removeAttribute('src'); // if the src attribute is used
audioElement.removeAttribute('srcObject'); // if the srcObject attribute is used
audioElement.load();
audioElement = null;
API Description
AudioMixerPlugin
The AudioMixerPlugin
plugin is used to implement the background music and audio effect features, which can be accessed
through TRTC.AudioMixerPlugin
.
isSupported()
is used to check whether the current browser environment supports adding background music to the audio track.createAudioMixer(params)
is used to create a music instance.mix(params)
is used to generate an audio track with background music.
isSupported()
This API is used to check whether the current browser supports the feature of adding background music. The returned
value is of Boolean
type. true
indicates that the feature is supported, while false
indicates not supported.
const result = AudioMixerPlugin.isSupported();
if (!result) {
alert('Your browser is not compatible with AudioMixerPlugin');
}
createAudioSource(params)
This API is used to create an AudioSource
music instance to add background music to the audio track.
Params
Name | Type | Attribute | Description |
---|---|---|---|
url | string |
Music file address | |
loop | boolean |
<optional> |
Whether to loop the music. Default value: false |
volume | number |
<optional> |
Initial volume. Default value: 1 |
Example:
Example 1. Create an instance through a file address
// Online file address
let audioSourceA = AudioMixerPlugin.createAudioSource({url: 'https://XXXX.mp3', loop: true, volume: 0.5});
// Relative file address
let audioSourceB = AudioMixerPlugin.createAudioSource({url: '../XXXX.mp3'});
audioSourceA.play();
Example 2. Select the blob URL generated by a local file to load the music file
// Use `<input type="file" id="fileInput">` to select the blob URL generated by a local file to load the music file
fileInput.addEventListener('change', function () {
var file = fileInput.files[0];
var reader = new FileReader();
reader.onload = function (e) {
let result = e.target.result;
let audioSourceC = AudioMixerPlugin.createAudioSource({url: result, loop: true, volume: 0.5});
};
reader.readAsDataURL(file);
});
createAudioSourceFromElement(element)
This API is used to create an AudioSource
music instance to add background music to the audio track.
Params:
Name | Type | Description |
---|---|---|
element | HTMLAudioElement |
HTMLAudioElement instance |
Example:
let audioSourceA = AudioMixerPlugin.createAudioSourceFromElement(document.getElementById('audioElementA'));
audioSourceA.play();
AudioSource
methods
Name | Type | Description |
---|---|---|
play() | Plays music | |
pause() | Pauses music | |
resume() | Resumes music | |
stop() | Stops music | |
duration() | Gets music duration in seconds | |
setPosition(time) | time: number (in seconds) |
Sets the music position, which cannot exceed the maximum music duration |
getPosition() | Gets the current music playback position | |
setVolume(volume) | volume: number (0 - 1) |
Sets the volume, which will affect both the local and remote playback volumes |
getVolume() | Gets volume | |
setPlayBackRate(rate) | rate: number (1 - 5) |
Sets playback rate. Value range: 1–5 |
getPlayBackRate() | Gets playback rate | |
loop(loop) | loop: boolean |
Sets whether to loop the playback. If loop is not passed in, the loop status will be returned |
on(eventName, handler) | eventName: number handler: function |
Listens on event |
off(eventName, handler) | eventName: number handler: function |
Cancels event listening |
Event list
The events that can be listened on are the same as the standard events of HTMLAudioElement
. For more information,
please see Events.
Name | Description |
---|---|
play | Music playback starts |
progress | Music is being loaded |
ended | Music playback ends |
...... | |
error | An error occurred, such as audio loading and playback exceptions. For more information, please see the FAQs |
// Listen on the playback event
audioSourceA.on('play', function play(event) {
console.log('play event trigger', event);
});
// Cancel listening on all events
audioSourceA.off('*', function cancel(event) {
console.log('Cancel listening on all events', event);
});
// Destroy audioSourceA
audioSourceA.destroy();
mix(params)
This API is used to mix the created music instance with the audio track. targetTrack
is the audio track to be mixed,
and sourceList
is the music instance array created by createAudioSource
, such as [ audioSourceA, audioSourceB ]
.
If targetTrack
is not passed in, an audio track containing only the background music will be generated.
Parameters
Name | Type | Description |
---|---|---|
targetTrack | MediaStreamTrack |
Target audio track |
sourceList | Array<AudioSource> |
AudioSource array object |
trackList | Array<MediaStreamTrack> |
AudioTrack array object |
Example:
Both targetTrack
and sourceList
are passed in:
// 1. Get the mic track
let originAudioTrack = localStream.getAudioTrack();
// 2. Mix the mic track with `audioSourceA` and `audioSourceB`
mixedAudioTrack = await AudioMixerPlugin.mix({targetTrack: originAudioTrack, sourceList: [audioSourceA, audioSourceB]});
// 3. Replace the mic track
await localStream.replaceTrack(mixedAudioTrack);
Only sourceList
array is passed in:
// Generate the background music containing only `audioSourceA` and `audioSourceB`
let bgmTrack = await AudioMixerPlugin.mix({sourceList: [audioSourceA, audioSourceB]});
destroySource(mixedAudioTrack)
When you unpublish or call leave to check out, you can use destroySource to clean up the resource.
client.leave();
audioSource.destroy();
AudioMixerPlugin.destroySource(mixedAudioTrack);
FAQs
1. What should I do if a CORS error occurs?
Example: Access to audio at XXX from origin XXX has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Solution: you need to configure the CORS protocol of the online music file.
2. What should I do if the audio format is incorrect and cannot be played back by the browser?
Example: NotSupportedError: The operation is not supported.
Solution: you need to use an audio format supported by the browser.
3. When you want to replace the background music after publishing it
Example: You want to replace the background music during the call after posting the background music.
Solution.
- You can re-capture a new audioTrack, use the same process to add new background music after, use LocalStream's replaceTrack method to replace the audio track being pushed to the stream, [click reference](https://web.sdk.qcloud.com/trtc/webrtc/ doc/zh-cn/tutorial-22-advanced-audio-mixer.html#h3-7).
- You can add multiple background sounds at the beginning, when you need a certain background music, call the background music audioSource.play() method to play it, if you don't need to play it, call the background music audioSource.pause() method to stop playing it.