Real-Time Streaming (RTS) delivers ultra-low latency live streaming through Alibaba Cloud CDN nodes using WebRTC signaling. Learn the WebRTC signaling specifications for accessing Global Realtime Transport Network (GRTN). Intended for developers with WebRTC experience.
Background information
TCP-based live streams have a latency of 3 to 6 seconds. To reduce latency, ApsaraVideo Live provides the RTS feature for UDP-based streaming. RTS delivers millisecond-latency, HD live streaming that supports tens of millions of concurrent requests. Beyond the RTS SDKs from ApsaraVideo Live, you can use your own clients to push or pull streams from CDN nodes through WebRTC-compatible signaling. ApsaraVideo Live provides global CDN nodes and optimized scheduling to operate the RTS service at scale.
GRTN performs well under poor network conditions.
Prerequisites
-
ApsaraVideo Live is activated. For more information, see Get started with ApsaraVideo Live.
-
RTS is enabled. For more information, see Step 5: Enable Real-Time Streaming (RTS).
-
An HTTPS SSL certificate is configured for the domain name. For more information, see Configure HTTPS secure acceleration.
Signaling process
The following figure shows the signaling process.

Signaling process
-
The client sends a request with an SDP offer.
-
Create an RTCPeerConnection object, specify whether to receive or send audio and video, and create an SDP offer.
// Specify whether to receive or send audio and video signals. { offerToReceiveVideo: true, offerToReceiveAudio: true } -
Send a stream pulling request to ApsaraVideo Live using HTTPS POST. The request body is a JSON string. For more information about the request parameters, see the Definition of the RTS signaling protocol section of this topic.
-
The
versionparameter specifies the RTS signaling protocol version. Set to 2. -
The
sdk_versionparameter specifies the RTS SDK version. Set as needed.
-
-
Send the request to ApsaraVideo Live using the signaling URL via POST. Include the source URL in the JSON request body.
POST /app/streamname?auth=xxx HTTP/1.1 Host: domain Connection: keep-alive Content-Length: 2205 Content-Type: application/jsonNoteA signaling URL matches the source URL except for the protocol header:
-
Signaling URL:
https://domain/app/streamname?auth=xxx -
Source URL:
artc://domain/app/streamname?auth=xxx
-
-
-
The server returns a response with an SDP answer.
After ApsaraVideo Live verifies the request, it generates an SDP answer and returns a response with the live streaming node information. For more information about the response parameters, see the Definition of the RTS signaling protocol section of this topic.
-
The client initiates Interactive Connectivity Establishment (ICE).
-
After receiving the SDP answer, set the session description on the RTCPeerConnection object.
peerConnection.setRemoteDescription(new RTCSessionDescription(answer.jsep)); -
Initiate ICE and DTLS encryption through the RTCPeerConnection object. After the signaling channel is established, the client pulls streams from ApsaraVideo Live using standard WebRTC playback.
-
-
The client initiates a disconnection.
The client sends a DTLS alert to stop stream ingest or playback.

Sample code for the HTML5 player
// Create peer connection and local offer sdp.
peerConnection = new RTCPeerConnection();
peerConnection.onicecandidate = iceCandidateCallback;
peerConnection.ontrack = remoteStreamCallback;
peerConnection.createOffer({ offerToReceiveVideo: true, offerToReceiveAudio: true })
.then(signaling_pull).catch(errorHandler);
// CDN live post pull stream request.
function signaling_pull(offer_sdp) {
console.log('local offer sdp', offer_sdp);
peerConnection.setLocalDescription(offer_sdp).then(function() {
// Get pull stream url.
var stream_url = $("#stream_url").val();
console.log("stream url:" , stream_url);
// Add sdk and protocol versions.
var protocol_version = 2;
var sdk_version = "0.0.1";
$.ajax({url: stream_url, data: JSON.stringify({
mode: "live",
version: protocol_version,
sdk_version: sdk_version,
jsep:description,
}),
type: "post",
success:function(result){
var signal = JSON.parse(result);
peerConnection.setRemoteDescription(new RTCSessionDescription(signal.jsep)).then(function() {
console.log("get remote answer sdp: ", signal.jsep.sdp);
}).catch(errorHandler);
}});
}).catch(errorHandler);
}
Definition of the RTS signaling protocol
The RTS signaling protocol uses a short-lived HTTPS connection with JSON messages. Sample code:
{
"version":2,
"sdk_version":"0.0.1",
"mode":"live",
"pull_streams":[
{
"url":"artc://your.domain.com/live/testname",
"amsid":[
"rts audio"
],
"vmsid":[
"rts video"
]
}
],
"jsep":{
"type":"offer",
"sdp":"v=0\n\ro=- 6839248142876176651 2 IN IP4 127.0.0.1\n\rs=-\n\r Omitted content"
}
}
Playback
-
Protocol description about playback
Table 1. Request parameters
Parameter
Type
Required
Description
mode
string
Yes
The stream mode. Set to live.
version
int
Yes
The protocol version. Set to 2.
push_stream
string
No
The ingest URL.
pull_streams
[]object
No
The streams to pull. Supports multiple streams. See the following table for attributes.
sdk_version
string
No
The SDK version.
jsep.type
string
Yes
The SDP message type. Set to offer.
jsep.sdp
string
Yes
The SDP message content.
Table 2. Attributes of the pull_stream parameter
Attribute
Type
Required
Description
url
string
Yes
The source URL that starts with
artc://.amsid
[]string
Yes
The audio stream MSID. Set to
rts audio.vmsid
[]string
Yes
The video stream MSID. Set to
rts video.Table 3. Response parameters
Parameter
Type
Required
Description
code
int
Yes
The HTTP status code. Returns 200 on success. See the Status codes table.
trace_id
string
Yes
The request GUID, generated by Alibaba Cloud CDN for troubleshooting. Retain this value.
jsep.type
string
Yes
The SDP message type. Returns answer.
jsep.sdp
string
Yes
The SDP message content generated when CDN nodes pull streams from the origin.
-
Playback request example
Request: { "version":2, "sdk_version":"0.0.1", "mode":"live", "pull_streams":[ { "url":"artc://your.domain.com/live/testname", "amsid":[ "rts audio" ], "vmsid":[ "rts video" ] } ], "jsep":{ "type":"offer", "sdp":"v=0\n\ro=- 6839248142876176651 2 IN IP4 127.0.0.1\n\rs=-\n\r Omitted content" } } Response: { "trace_id":"2_1591173296_101.227.0.169_702080732320_dec327eb6eed0e0b07b349c8a5653eca", "code":200, "jsep":{ "type":"answer", "sdp":"v=0\r\no=- 1591173291 2 IN IP4 127.0.0.1\n\r Omitted content" } }sps-pps-idr-in-keyframe: To prevent screen flicker during browser playback under poor network conditions, modify the SDP as follows.
After creating an SDP offer for HTML5 playback and before calling setLocalDescription, find the H.264 video attribute line:
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001fAppend sps-pps-idr-in-keyframe=1:
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f;sps-pps-idr-in-keyframe=1GRTN enables this feature in response.
-
Error handling
A valid request returns HTTP 200. Error responses include code and message in the JSON body:
Response: { "code": 200, // A value of 200 indicates that the request is successful. For more information about status codes, see the "Status codes" section. "message": "success" // The returned message. }Table 4. Response parameters
Parameter
Type
Description
code
int
The HTTP status code. See the Status codes table.
message
string
The returned message.
Table 5. Status codes
Status code
Description
403
Authentication failed.
404
Stream does not exist.
611
Client must play the stream over TCP.
302
Client must redirect the request to a new address.
Stream ingest
-
Protocol description about stream ingest
Table 6. Request parameters
Parameter
Type
Required
Description
mode
string
Yes
The stream mode. Set to live.
version
int
Yes
The protocol version. Set to 2.
push_stream
string
No
The ingest URL.
sdk_version
string
No
The SDK version.
jsep.type
string
Yes
The SDP message type. Set to offer.
jsep.sdp
string
Yes
The SDP message content.
Table 7. Response parameters
Parameter
Type
Required
Description
code
int
Yes
The HTTP status code. Returns 200 on success. See the Status codes table.
trace_id
string
Yes
The request GUID, generated by Alibaba Cloud CDN for troubleshooting. Retain this value.
jsep.type
string
Yes
The SDP message type. Returns answer.
jsep.sdp
string
Yes
The SDP message content generated when CDN nodes pull streams from the origin.
-
Stream ingest request example
Request: { "version":2, "sdk_version":"0.0.1", "mode":"rtc", "push_stream":"artc://host/app/name", "jsep":{ "type":"offer", "sdp":"v=0\r\no=- 1385856200224536561 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1 2\r\na=extmap-allow-mixed\r\na=msid-semantic: WMS rts\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111 63 103 104 9 0 8 106 105 13 110 112 113 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:iQyM\r\na=ice-pwd:D3GXKCcUGvW9djaAozff5ppT\r\na=ice-options:trickle\r\na=fingerprint:sha-256 20:50:72:9B:A2:C0:D8:50:AD:D0:EF:A7:62:8F:EF:C3:AB:86:D5:B6:3E:17:22:69:79:5B:CE:E8:42:33:B5:E4\r\na=setup:actpass\r\na=mid:0\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=sendrecv\r\na=msid:rts audio\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=rtcp-fb:111 transport-cc\r\na=rtcp-fb:111 nack\r\na=fmtp:111 minptime=10;useinbandfec=1\r\na=rtpmap:63 red/48000/2\r\na=fmtp:63 111/111\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:110 telephone-event/48000\r\na=rtpmap:112 telephone-event/32000\r\na=rtpmap:113 telephone-event/16000\r\na=rtpmap:126 telephone-event/8000\r\na=ssrc:3411287802 cname:s4eR7OuKnnPL0vKS\r\na=ssrc:3411287802 msid:rts audio\r\na=ssrc:3411287802 mslabel:rts\r\na=ssrc:3411287802 label:audio\r\nm=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 127 121 125 107 108 109 124 120 123 119 35 36 41 42 114 115 116 117 118\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:iQyM\r\na=ice-pwd:D3GXKCcUGvW9djaAozff5ppT\r\na=ice-options:trickle\r\na=fingerprint:sha-256 20:50:72:9B:A2:C0:D8:50:AD:D0:EF:A7:62:8F:EF:C3:AB:86:D5:B6:3E:17:22:69:79:5B:CE:E8:42:33:B5:E4\r\na=setup:actpass\r\na=mid:1\r\na=extmap:14 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:13 urn:3gpp:video-orientation\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type\r\na=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing\r\na=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space\r\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\na=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\r\na=sendrecv\r\na=msid:rts video\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:96 VP8/90000\r\na=rtcp-fb:96 goog-remb\r\na=rtcp-fb:96 transport-cc\r\na=rtcp-fb:96 ccm fir\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 nack pli\r\na=rtpmap:97 rtx/90000\r\na=fmtp:97 apt=96\r\na=rtpmap:98 VP9/90000\r\na=rtcp-fb:98 goog-remb\r\na=rtcp-fb:98 transport-cc\r\na=rtcp-fb:98 ccm fir\r\na=rtcp-fb:98 nack\r\na=rtcp-fb:98 nack pli\r\na=fmtp:98 profile-id=0\r\na=rtpmap:99 rtx/90000\r\na=fmtp:99 apt=98\r\na=rtpmap:100 VP9/90000\r\na=rtcp-fb:100 goog-remb\r\na=rtcp-fb:100 transport-cc\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack\r\na=rtcp-fb:100 nack pli\r\na=fmtp:100 profile-id=2\r\na=rtpmap:101 rtx/90000\r\na=fmtp:101 apt=100\r\na=rtpmap:127 H264/90000\r\na=rtcp-fb:127 goog-remb\r\na=rtcp-fb:127 transport-cc\r\na=rtcp-fb:127 ccm fir\r\na=rtcp-fb:127 nack\r\na=rtcp-fb:127 nack pli\r\na=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f\r\na=rtpmap:121 rtx/90000\r\na=fmtp:121 apt=127\r\na=rtpmap:125 H264/90000\r\na=rtcp-fb:125 goog-remb\r\na=rtcp-fb:125 transport-cc\r\na=rtcp-fb:125 ccm fir\r\na=rtcp-fb:125 nack\r\na=rtcp-fb:125 nack pli\r\na=fmtp:125 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f\r\na=rtpmap:107 rtx/90000\r\na=fmtp:107 apt=125\r\na=rtpmap:108 H264/90000\r\na=rtcp-fb:108 goog-remb\r\na=rtcp-fb:108 transport-cc\r\na=rtcp-fb:108 ccm fir\r\na=rtcp-fb:108 nack\r\na=rtcp-fb:108 nack pli\r\na=fmtp:108 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f\r\na=rtpmap:109 rtx/90000\r\na=fmtp:109 apt=108\r\na=rtpmap:124 H264/90000\r\na=rtcp-fb:124 goog-remb\r\na=rtcp-fb:124 transport-cc\r\na=rtcp-fb:124 ccm fir\r\na=rtcp-fb:124 nack\r\na=rtcp-fb:124 nack pli\r\na=fmtp:124 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f\r\na=rtpmap:120 rtx/90000\r\na=fmtp:120 apt=124\r\na=rtpmap:123 H264/90000\r\na=rtcp-fb:123 goog-remb\r\na=rtcp-fb:123 transport-cc\r\na=rtcp-fb:123 ccm fir\r\na=rtcp-fb:123 nack\r\na=rtcp-fb:123 nack pli\r\na=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f\r\na=rtpmap:119 rtx/90000\r\na=fmtp:119 apt=123\r\na=rtpmap:35 H264/90000\r\na=rtcp-fb:35 goog-remb\r\na=rtcp-fb:35 transport-cc\r\na=rtcp-fb:35 ccm fir\r\na=rtcp-fb:35 nack\r\na=rtcp-fb:35 nack pli\r\na=fmtp:35 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=4d001f\r\na=rtpmap:36 rtx/90000\r\na=fmtp:36 apt=35\r\na=rtpmap:41 AV1/90000\r\na=rtcp-fb:41 goog-remb\r\na=rtcp-fb:41 transport-cc\r\na=rtcp-fb:41 ccm fir\r\na=rtcp-fb:41 nack\r\na=rtcp-fb:41 nack pli\r\na=rtpmap:42 rtx/90000\r\na=fmtp:42 apt=41\r\na=rtpmap:114 H264/90000\r\na=rtcp-fb:114 goog-remb\r\na=rtcp-fb:114 transport-cc\r\na=rtcp-fb:114 ccm fir\r\na=rtcp-fb:114 nack\r\na=rtcp-fb:114 nack pli\r\na=fmtp:114 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f\r\na=rtpmap:115 rtx/90000\r\na=fmtp:115 apt=114\r\na=rtpmap:116 red/90000\r\na=rtpmap:117 rtx/90000\r\na=fmtp:117 apt=116\r\na=rtpmap:118 ulpfec/90000\r\na=ssrc-group:FID 4075787827 945566690\r\na=ssrc:4075787827 cname:s4eR7OuKnnPL0vKS\r\na=ssrc:4075787827 msid:rts video\r\na=ssrc:4075787827 mslabel:rts\r\na=ssrc:4075787827 label:video\r\na=ssrc:945566690 cname:s4eR7OuKnnPL0vKS\r\na=ssrc:945566690 msid:rts video\r\na=ssrc:945566690 mslabel:rts\r\na=ssrc:945566690 label:video\r\nm=application 9 UDP/DTLS/SCTP webrtc-datachannel\r\nc=IN IP4 0.0.0.0\r\na=ice-ufrag:iQyM\r\na=ice-pwd:D3GXKCcUGvW9djaAozff5ppT\r\na=ice-options:trickle\r\na=fingerprint:sha-256 20:50:72:9B:A2:C0:D8:50:AD:D0:EF:A7:62:8F:EF:C3:AB:86:D5:B6:3E:17:22:69:79:5B:CE:E8:42:33:B5:E4\r\na=setup:actpass\r\na=mid:2\r\na=sctp-port:5000\r\na=max-message-size:262144\r\n" } } Response: { "trace_id":"...", "code":200, "jsep":{ "type":"answer", "sdp":"v=0\r\no=- 1657264764 2 IN IP4 127.0.0.1 Omitted content" } }In the preceding signaling request, push_stream specifies the ingest URL, similar to RTMP stream ingest. Note the following:
-
You must specify an MSID in the SDP message. GRTN uses the MSID to identify media streams.
-
Codec negotiation is not supported. Each MSID allows only one codec. GRTN does not negotiate codecs. Supported codecs: AAC, Opus, H.264, and H.265.
-
Sample code for audio


-
video


-
-
Error handling
A valid request returns HTTP 200. Error responses include code and message in the JSON body:
Response: { "code": 200, // A value of 200 indicates that the request is successful. For more information about status codes, see the "Status codes" section. "message": "success" // The returned message. }Table 8. Response parameters
Parameter
Type
Description
code
int
The HTTP status code. See the Status codes table.
message
string
The returned message.
Table 9. Status codes
Status code
Description
403
Authentication failed.
611
Client must play the stream over TCP.
302
Client must redirect the request to a new address.
Enhanced SDP negotiation
SDP negotiation follows RFC 4566 with RTS-specific extensions for live streaming. RTS extends standard SDP semantics to support more video and audio container formats and communication protocols, resolving WebRTC limitations such as Opus-only audio and no B-frame support.
AAC supported for stream ingest and pulling
RTS can transmit audio in various AAC formats over RTMP. The AAC formats include AAC-LC, HE-AACv1, and HE-AACv2.
RTS transmits AAC audio using the LATM container format. LATM determines whether audio encoding information is transmitted in-band (per frame) or out-of-band (once) based on the muxconfigPresent parameter in the AudioMuxElement array. This makes LATM more flexible than ADTS. When AudioSpecificConfig remains unchanged, StreamMuxConfig can be transmitted in the SDP message first.
-
AAC supported for stream ingest
Carry the AAC audio format information in the SDP offer. Add config=StreamMuxConfig (obtained from AudioSpecificConfig of the ingested stream) in the fmtp attribute to pass the AudioSpecificConfig to the server for AAC header generation.
SDP offer
a=rtpmap:125 MP4A-LATM/48000/2 a=fmtp:125 config=4000232000;cpresent=0;object=2;profile-level-id=1 -
AAC supported for stream pulling
During signaling, RTS parses the audio encoding information and returns the result in the negotiation response:
SDP offer
SDP answer
AAC-LC
HE-AACv1
HE-AACv2
m=audio 9 UDP/RTP/AVPF 120 96 a=rtpmap:120 MP4A-LATM/44100/2AudioSpecificConfig = 0x1210AudioSpecificConfig = 2b920800AudioSpecificConfig = eb8a0800a=rtpmap:120 MP4A-LATM/44100/2 a=fmtp:120 cpresent=0;profile-level-id=1;object=2;config=400024203fc0a=rtpmap:120 MP4A-LATM/44100/2 a=fmtp:120 cpresent=0;profile-level-id=1;object=2;config=4000572410003fc0;SBR-enabled=1a=rtpmap:120 MP4A-LATM/44100/2 a=fmtp:120 cpresent=0;object=2;profile-level-id=1;config=4001d71410003fc0;PS-enabled=1;SBR-enabled=1If
SBR-enabled=1is in the fmtp attribute, the format is HE-AAC. If bothSBR-enabled=1andPS-enabled=1are present, the format is HE-AACv2. You can also addconfig=StreamMuxConfigin the fmtp attribute, where StreamMuxConfig (from AudioSpecificConfig) contains detailed encoding parameters.
H.265 supported for stream ingest and pulling
-
H.265 supported for stream ingest
Carry the H.265 video format information in the SDP offer.
SDP offer:
a=rtpmap:102 H265/90000 -
H.265 supported for stream pulling
During stream pulling signaling, the server detects the source stream video codec (H.264 or H.265) and negotiates accordingly.
SDP offer
SDP answer
a=rtpmap:102 H265/90000a=rtpmap:122 H265/90000 a=fmtp:122
B-frames supported for stream ingest and pulling
-
B-frames supported for stream ingest
B-frames are supported in the ingested stream.
-
B-frames supported for stream pulling
During signaling, the client can add a field in the SDP offer to specify B-frame decoding support. Adding
BFrame-enabled = 1in the fmtp attribute enables B-frame decoding, whereRTP timestamp = PTSmeans the client decodes frames in increasing sequence number order. If B-frames are not supported, RTS transcodes the source stream to remove them.For B-frame decoding, "RTP timestamp = PTS" is used and the client decodes frames by increasing sequence number.
The server can also return a composition timestamp (CTS), allowing the client to calculate the decoding timestamp (DTS) as: PTS = DTS + CTS. If the SDP offer contains
a=extmap:{$id} uri:webrtc:rtc:rtp-hdrext:video:CompositionTime, RTS addsextension identifier = {$id}to the first RTP packet of each video frame. Theidvalue is determined by the client's SDP offer.RTS lets the client control B-frame decoding and CTS return independently.
The following figures show partial SDP offer content and packet capture during stream pulling:


Signaling request carrying metadata supported for stream ingest
RTMP ingested streams carry metadata for callbacks and stream pulling clients. Since WebRTC signaling does not include metadata, RTS allows metadata in the signaling request body to generate metadata in the ingested stream.
Add the metadata field to the body of the signaling request for the ingested stream:
{
"version":2,
"sdk_version":"0.0.1",
"mode":"rtc",
"push_stream":"artc://host/app/name",
"jsep":{
"type":"offer",
"sdp":"..."
},
"metadata":{
"framerate":"20",
"platform":"iOS",
"audiodatarate":"200",
"videodatarate":"2000"
}
}
MSID mechanism
The MSID mechanism is defined in The Msid Mechanism. Note the following: