Home

Awesome

<a href='https://patreon.com/stefansarya'><img src='https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.herokuapp.com%2Fstefansarya%2Fpledges&style=for-the-badge' height='20'></a>

Written by Software License Tweet

SFMediaStream

A HTML5 media streamer library for playing music, video, or even microphone & camera live streaming with node server. The transmitted data is compressed (depend on the browser media encoder) before being sent to node server, and the latency is configurable.

The default configuration is intended for newer browser. If you want to build 2-way communication for older and newer browser, then you must send streamer encoding information to the presenter before start the communication or using mp4 instead of opus.

Install with CDN link

You can download minified js from this repository or use this CDN link <script type="text/javascript" src='https://cdn.jsdelivr.net/npm/sfmediastream@latest'></script>

And include it on your project

var presenter = new ScarletsMediaPresenter(...);
var streamer = new ScarletsAudioStreamer(...);

Install with NPM

npm i sfmediastream

And include it on your project

const {MediaPresenter, AudioStreamer, ...} = require('sfmediastream');
var presenter = new MediaPresenter(...);
var streamer = new AudioStreamer(...);

How to use

ScarletsMediaPresenter

This class is used for streaming local media like camera or microphone to the server.

Properties

PropertyDetails
debugSet to true for outputting any message to browser console
mediaRecorderReturn current mediaRecorder that being used
mediaStreamReturn current mediaStream that being used
mediaGrantedReturn true if user granted the recorder
recordingReadyReturn true if the recording was ready
recordingReturn true if currently recording
destinationUsed for connect audio node to the recorder
options.mimeTypeReturn mimeType that being used
// Example for accessing the properties
presenterMedia.debug = true;

Method

FunctionArgumentsDescription
startRecording()Start recording camera or microphone
stopRecording()Stop recording camera or microphone
connect(AudioNode)Connect presenter's stream to audio processing before being recorded and disable direct output
disconnect(AudioNode)Disconnect presenter's stream from audio processing

Event Listener

onRecordingReady

Callback when the library is ready for recording

presenterMedia.onRecordingReady = function(packet){
    console.log("Header size: " + packet.data.size);
    mySocket.emit('bufferHeader', packet);
};
onBufferProcess

Callback when data buffer is ready to be played

presenterMedia.onBufferProcess = function(packet){
    console.log("Data", packet);
    mySocket.emit('stream', packet);
};

Example

var presenterMedia = new ScarletsMediaPresenter({
    audio:{
        channelCount:1,
        echoCancellation: false
    },/* video:{
        frameRate:15,
        width: 1280,
        height: 720,
        facingMode: (frontCamera ? "user" : "environment")
    } */
}, 1000); // 1sec

presenterMedia.onRecordingReady = function(packet){
    console.log("Recording started!");
    console.log("Header size: " + packet.data.size + "bytes");

    // Every new streamer must receive this header packet
    mySocket.emit('bufferHeader', packet);
}

presenterMedia.onBufferProcess = function(packet){
    console.log("Buffer sent: " + packet[0].size + "bytes");
    mySocket.emit('stream', packet);
}

presenterMedia.startRecording();
presenterMedia.stopRecording();

ScarletsAudioStreamer

This class is used for buffering and playing microphone stream from the server.

// The minimum duration for audio is ~100ms
var audioStreamer = new ScarletsAudioStreamer(1000); // 1sec

Properties

PropertyDetails
debugSet to true for outputting any message to browser console
playingReturn true if playing a stream
latencyReturn current latency
mimeTypeReturn mimeType of current streamed media
outputNodeWill be available when using .connect(AudioNode)
// Example for accessing the properties
audioStreamer.debug = true;

Method

FunctionArgumentsDescription
playStream()Set this library to automatically play any received buffer
receiveBuffer(packetBuffer)Receive arrayBuffer and play it when last buffer finished playing
realtimeBufferPlay(packetBuffer)Receive arrayBuffer and immediately play it
stop()Stop playing any buffer
connect(AudioNode)Connect the streamer to other AudioNode
disconnect(AudioNode)Disconnect the streamer from any AudioNode

ScarletsVideoStreamer

This class is used for buffering and playing microphone & camera stream from the server.

Still in experimental mode and have some bug.

// Usually the minimum duration for video is 1000ms
var videoStreamer = new ScarletsVideoStreamer(videoHTML, 1000); // 1sec

Properties

PropertyDetails
debugSet to true for outputting any message to browser console
playingReturn true if playing a stream
latencyReturn current latency
mimeTypeReturn mimeType of current streamed media
outputNodeWill be available when using .connect(AudioNode)
// Example for accessing the properties
videoStreamer.debug = true;

Method

FunctionArgumentsDescription
playStream()Set this library to automatically play any received buffer
receiveBuffer(arrayBuffer)Receive arrayBuffer and play it when last buffer finished playing
stop()Stop playing any buffer
audioConnect(AudioNode)Connect the streamer to other AudioNode
audioDisconnect(AudioNode)Disconnect the streamer from any AudioNode

Example

// var audioStreamer = new ScarletsAudioStreamer(1000); // 1sec
var videoStreamer = new ScarletsVideoStreamer(1000); // 1sec
videoStreamer.playStream();

// First thing that must be received
mySocket.on('bufferHeader', function(packet){
    videoStreamer.setBufferHeader(packet);
});

mySocket.on('stream', function(packet){
    console.log("Buffer received: " + packet[0].byteLength + "bytes");
    videoStreamer.receiveBuffer(packet);
});

// Add an effect
var ppDelay = ScarletsMediaEffect.pingPongDelay();

// Stream (source) -> Ping pong delay -> destination
videoStreamer.audioConnect(ppDelay.input);
ppDelay.output.connect(ScarletsMedia.audioContext.destination);

ScarletsMediaPlayer

This class is used for playing video or audio from url.

var mediaPlayer = new ScarletsMediaPlayer(document.querySelector('audio'));

Properties

PropertyDetails
autoplaySets or returns whether the audio/video should start playing as soon as it is loaded
preloadSets or returns whether the audio/video should be loaded when the page loads
loopSets or returns whether the audio/video should start over again when finished
bufferedReturns a TimeRanges object representing the buffered parts of the audio/video
preloadSets or returns whether the audio/video should be loaded when the page loads ("none", "metadata", "auto")
controllerReturns the MediaController object representing the current media controller of the audio/video
currentTimeSets or returns the current playback position in the audio/video (in seconds)
currentSrcReturns the URL of the current audio/video
durationReturns the length of the current audio/video (in seconds)
endedReturns whether the playback of the audio/video has ended or not
errorReturns a MediaError object representing the error state of the audio/video
readyStateReturns the current ready state of the audio/video
networkStateReturns the current network state of the audio/video
pausedReturns whether the audio/video is paused or not
playedReturns a TimeRanges object representing the played parts of the audio/video
seekableReturns a TimeRanges object representing the seekable parts of the audio/video
seekingReturns whether the user is currently seeking in the audio/video
audioOutputReturn audioContext from media source
videoOutputReturn videoContext from media source
The videoContext still in experimental mode and haven't been implemented.
// Example for accessing the properties
mediaPlayer.preload = "metadata";

Method

FunctionArgumentsDescription
load()Re-loads the audio/video element
canPlayType(str)Checks if the browser can play the specified audio/video type
speed(0 ~ 1)Sets or returns the speed of the audio/video playback
mute(boolean)Sets or returns whether the audio/video is muted or not
volume(0 ~ 1)Sets or returns the volume of the audio/video
play()Starts playing the audio/video
pause()Pauses the currently playing audio/video

Below also the available method.

prepare

Load media from URL

mediaPlayer.prepare('my.mp3' /*single*/ || /*with fallback*/ ['my.mp3', 'fallback.ogg'], function(){
    mediaPlayer.play();
});
on

Register event callback

mediaPlayer.on('loadedmetadata', function(e){
    // See at the property above
    console.log(e.target.duration);
});
off

Un-register event callback

mediaPlayer.off('abort');
once

Register event callback and remove listener after called

mediaPlayer.once('abort', function(e){
    alert('User aborted the buffer');
});

Available Events

EventDetails
abortFires when the loading of an audio/video is aborted
canplayFires when the browser can start playing the audio/video
canplaythroughFires when the browser can play through the audio/video without stopping for buffering
durationchangeFires when the duration of the audio/video is changed
emptiedFires when the current player is empty
endedFires when the current player is ended
errorFires when an error occurred during the loading of an audio/video
loadeddataFires when the browser has loaded the current frame of the audio/video
loadedmetadataFires when the browser has loaded meta data for the audio/video
loadstartFires when the browser starts looking for the audio/video
pauseFires when the audio/video has been paused
playFires when the audio/video has been started or is no longer paused
playingFires when the audio/video is playing after having been paused or stopped for buffering
progressFires when the browser is downloading the audio/video
ratechangeFires when the playing speed of the audio/video is changed
seekedFires when the user is finished moving/skipping to a new position in the audio/video
seekingFires when the user starts moving/skipping to a new position in the audio/video
stalledFires when the browser is trying to get media data, but data is not available
suspendFires when the browser is intentionally not getting media data
timeupdateFires when the current playback position has changed
volumechangeFires when the volume has been changed
waitingFires when the video stops because it needs to buffer the next frame
playlistchangeFires when the player starts another playlist

playlistchange the callback function will get (player, playlist, index) as the arguments.

Video Properties

PropertyDetails
posterSpecifies an image to be shown while the video is downloading, or until the user hits the play button
heightSets the height of the video player
widthSets the width of the video player
// Example for accessing the properties
mediaPlayer.poster = 'url.png';

Properties

audioFadeEffect

Enable fade effect when playing or pausing the sound

mediaPlayer.audioFadeEffect = true;
audioOutput

Can be used to connect the media to other effect or plugin like equalizer

// Create equalizer and pass audio output as equalizer input
var equalizer = ScarletsMediaEffect.equalizer(null, mediaPlayer.audioOutput);

// Connect to final destination
equalizer.output.connect(ScarletsMedia.audioContext.destination);

ScarletsMediaEffect

This feature can be used on every media if you have the media source node as the input. And make sure every node is connected to AudioContext.destination or it will not playable.

The plugins have a function to destroy node connection that aren't being used. So don't forget to destroy your unused effect to clean unused memory.

effect.destroy();

Available Plugin

EffectDetails
ChorusAn effect to make a single voice like multiple voices
ConReverbAn reverb effect that simulates from other audio source
CutOffAn cutoff filter that have adjustable width
DelayAn effect that play the audio back after a period of time
DistortionIt's.. like.. distortion..
DubDelayDelay with feedback saturation and time/pitch modulation
EqualizerAdjustable frequency pass filter
FadeVolume fade in and fade out effect
FlangerAn audio effect by mixing two identical signals together with one signal who get delayed
HarmonizerAn pitch shift effect which like playing an harmony
NoiseNoise generator like a radio
PingPongDelayStereo delay effect that alternates each delay between the left and right channels
ReverbConfigurable reflection effect
StereoPannerCan be used to pan an audio stream left or right
TremoloModulation effect that creates a change in volume
// Directly connect audio output as an input for ping pong delay plugin
var ppDelay = ScarletsMediaEffect.pingPongDelay(mediaPlayer.audioOutput);

// Create StereoPanner handler
var panner = ScarletsMediaEffect.stereoPanner(/* input [optional] */);
// panner.input (will be available if no input passed on plugin)

// Connect ppDelay output to panner input
ppDelay.output.connect(panner.input);

// Modify the plugin (Still need to be documented)
panner.set(-1); // Left channel

// Connect to final destination
panner.connect(ScarletsMedia.audioContext.destination);

// Visualization
// player.audioOutput -> pingPongDelay -> Panner -> final destination

Playlist

This will be available on current media player

Properties

PropertyDetails
currentIndexReturn index of current playing media
listReturn array playlist that are being used
originalReturn original array playlist
loopSet this to true if you want to play this playlist again from beginning
shuffledReturn true if the list was shuffled
// Example for accessing the properties
console.log('Current playlist count', mediaPlayer.playlist.original.length);

Method

reload

Replace old playlist data

mediaPlayer.playlist.reload([{
    yourProperty:'',
    stream:['main.mp3', 'fallback.ogg']
}, ...]);
add

Add new data to playlist

mediaPlayer.playlist.add({
    yourProperty:'',
    stream:['main.mp3', 'fallback.ogg']
});
remove

Remove original playlist data by index

// mediaPlayer.playlist.original[0]
mediaPlayer.playlist.remove(0);
next

Play next music, this will also trigger playlistchange event

mediaPlayer.playlist.next();
previous

Play previous music, this will also trigger playlistchange event

mediaPlayer.playlist.previous();
play

Play music by index

// mediaPlayer.playlist.list[0]
mediaPlayer.playlist.play(0);
shuffle

Shuffle the playlist

// mediaPlayer.playlist.list
mediaPlayer.playlist.shuffle(true || false);

Contribution

If you want to help in SFMediaStream please fork this project and edit on your repository, then make a pull request to here. Otherwise, you can help with donation via patreon.

Compile from source

After you downloaded this repo you need to install some devDependencies.

$ npm i
$ gulp watch

After you make some changes on /src it will automatically compile into /dist/SFMediaStream.js. Make sure you cleared your cache when doing some experiment.

License

SFMediaStream is under the MIT license.

But don't forget to put the a link to this repository.