The RTMP Live Streaming service provides capabilities for creating and managing live streaming channels, controlling streaming status, and generating Video-on-Demand (VOD) content from live streams.
async function putChannel(id: string, conf: ChannelConfig, options?: RequestOptions): Promise<PutChannelResult>;
interface ChannelConfig {
name: string;
description?: string;
status?: 'enabled' | 'disabled';
type?: 'HLS';
fragDuration?: number;
fragCount?: number;
playlistName?: string;
}
interface PutChannelResult {
publishUrls: string[];
playUrls: string[];
res: ResponseInfo;
}async function getChannel(id: string, options?: RequestOptions): Promise<GetChannelResult>;
interface GetChannelResult {
name: string;
description?: string;
status: 'enabled' | 'disabled';
type: string;
fragDuration: number;
fragCount: number;
playlistName: string;
createTime: Date;
lastModified: Date;
res: ResponseInfo;
}async function deleteChannel(id: string, options?: RequestOptions): Promise<DeleteChannelResult>;
interface DeleteChannelResult {
res: ResponseInfo;
}async function listChannels(query?: ListChannelsQuery, options?: RequestOptions): Promise<ListChannelsResult>;
interface ListChannelsQuery {
prefix?: string;
marker?: string;
'max-keys'?: number;
}
interface ListChannelsResult {
channels: ChannelInfo[];
isTruncated: boolean;
nextMarker?: string;
res: ResponseInfo;
}
interface ChannelInfo {
name: string;
description?: string;
status: 'enabled' | 'disabled';
lastModified: Date;
publishUrls: string[];
playUrls: string[];
}async function putChannelStatus(id: string, status: 'enabled' | 'disabled', options?: RequestOptions): Promise<PutChannelStatusResult>;
interface PutChannelStatusResult {
res: ResponseInfo;
}async function getChannelStatus(id: string, options?: RequestOptions): Promise<GetChannelStatusResult>;
interface GetChannelStatusResult {
status: 'Live' | 'Idle';
connectedTime?: Date;
remoteAddr?: string;
video?: VideoInfo;
audio?: AudioInfo;
res: ResponseInfo;
}
interface VideoInfo {
width: number;
height: number;
frameRate: number;
bandwidth: number;
codec: string;
}
interface AudioInfo {
bandwidth: number;
sampleRate: number;
codec: string;
}async function getChannelHistory(id: string, options?: RequestOptions): Promise<GetChannelHistoryResult>;
interface GetChannelHistoryResult {
records: StreamRecord[];
res: ResponseInfo;
}
interface StreamRecord {
startTime: Date;
endTime: Date;
remoteAddr: string;
}async function createVod(id: string, name: string, time: VodTime, options?: RequestOptions): Promise<CreateVodResult>;
interface VodTime {
startTime: number; // Unix timestamp in seconds (epoch time)
endTime: number; // Unix timestamp in seconds (epoch time)
}
interface CreateVodResult {
res: ResponseInfo;
}function getRtmpUrl(channelId: string, options?: RtmpUrlOptions): string;
interface RtmpUrlOptions {
expires?: number; // URL expiration time in seconds
params?: Record<string, string>; // Additional URL parameters for authentication or configuration
}const OSS = require('ali-oss');
const client = new OSS({
region: 'oss-cn-hangzhou',
accessKeyId: 'your-access-key-id',
accessKeySecret: 'your-access-key-secret',
bucket: 'your-live-bucket'
});
// Create a live channel
const channelResult = await client.putChannel('live-channel-1', {
name: 'My Live Stream',
description: 'Live streaming channel for events',
status: 'enabled',
type: 'HLS',
fragDuration: 5, // 5 second fragments
fragCount: 3, // Keep 3 fragments in playlist
playlistName: 'playlist.m3u8'
});
console.log('Publish URLs:', channelResult.publishUrls);
console.log('Play URLs:', channelResult.playUrls);// List all channels
const channels = await client.listChannels({
prefix: 'live-',
'max-keys': 10
});
console.log('Active channels:', channels.channels.length);
// Get specific channel info
const channelInfo = await client.getChannel('live-channel-1');
console.log('Channel status:', channelInfo.status);
console.log('Created:', channelInfo.createTime);
// Check if channel is currently streaming
const status = await client.getChannelStatus('live-channel-1');
if (status.status === 'Live') {
console.log('Stream is live!');
console.log('Connected from:', status.remoteAddr);
console.log('Video:', `${status.video.width}x${status.video.height} @ ${status.video.frameRate}fps`);
} else {
console.log('Channel is idle');
}// Enable/disable channel
await client.putChannelStatus('live-channel-1', 'enabled');
console.log('Channel enabled');
// Disable channel (stops any active streams)
await client.putChannelStatus('live-channel-1', 'disabled');
console.log('Channel disabled');
// Get streaming history
const history = await client.getChannelHistory('live-channel-1');
console.log('Stream sessions:', history.records.length);
history.records.forEach(record => {
console.log(`Session: ${record.startTime} - ${record.endTime} from ${record.remoteAddr}`);
});// Create VOD from live stream segment
await client.createVod('live-channel-1', 'highlight-clip', {
startTime: Math.floor(Date.now() / 1000) - 3600, // 1 hour ago
endTime: Math.floor(Date.now() / 1000) - 3000 // 50 minutes ago
});
console.log('VOD playlist created');// Generate RTMP publish URL with expiration
const publishUrl = client.getRtmpUrl('live-channel-1', {
expires: 3600, // 1 hour
params: {
'stream-key': 'secure-stream-key-123'
}
});
console.log('Publish URL:', publishUrl);
// Use this URL in streaming software like OBS// Create channel optimized for high-quality streaming
const hqChannel = await client.putChannel('hq-stream', {
name: 'High Quality Stream',
description: 'HD streaming channel',
status: 'enabled',
type: 'HLS',
fragDuration: 2, // Shorter fragments for lower latency
fragCount: 5, // More fragments for better buffering
playlistName: 'hq-playlist.m3u8'
});// Create multiple channels for different purposes
const channels = [
{ id: 'main-stage', name: 'Main Stage', description: 'Primary event stream' },
{ id: 'backstage', name: 'Backstage', description: 'Behind the scenes' },
{ id: 'audience', name: 'Audience View', description: 'Audience perspective' }
];
for (const channel of channels) {
const result = await client.putChannel(channel.id, {
name: channel.name,
description: channel.description,
status: 'enabled',
type: 'HLS',
fragDuration: 3,
fragCount: 4
});
console.log(`Channel ${channel.id} created`);
console.log(`Publish: ${result.publishUrls[0]}`);
console.log(`Play: ${result.playUrls[0]}`);
}async function monitorChannels(channelIds) {
const report = {
live: [],
idle: [],
total: channelIds.length
};
for (const channelId of channelIds) {
try {
const status = await client.getChannelStatus(channelId);
if (status.status === 'Live') {
report.live.push({
id: channelId,
connectedTime: status.connectedTime,
remoteAddr: status.remoteAddr,
video: status.video,
audio: status.audio
});
} else {
report.idle.push(channelId);
}
} catch (error) {
console.error(`Failed to check status for ${channelId}:`, error);
}
}
return report;
}
// Monitor channels every 30 seconds
setInterval(async () => {
const report = await monitorChannels(['main-stage', 'backstage', 'audience']);
console.log(`Live channels: ${report.live.length}/${report.total}`);
}, 30000);async function analyzeStreamHistory(channelId, days = 7) {
const history = await client.getChannelHistory(channelId);
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - days);
const recentSessions = history.records.filter(
record => record.startTime >= cutoffDate
);
const totalDuration = recentSessions.reduce((total, record) => {
return total + (record.endTime.getTime() - record.startTime.getTime());
}, 0);
return {
sessionCount: recentSessions.length,
totalDurationHours: totalDuration / (1000 * 60 * 60),
averageDurationMinutes: (totalDuration / recentSessions.length) / (1000 * 60),
uniqueIPs: [...new Set(recentSessions.map(r => r.remoteAddr))].length
};
}try {
await client.putChannel('new-channel', channelConfig);
} catch (error) {
if (error.code === 'ChannelAlreadyExists') {
console.log('Channel already exists, updating configuration...');
// Update existing channel or use different name
} else if (error.code === 'InvalidChannelName') {
console.error('Invalid channel name format');
} else {
console.error('Channel creation failed:', error.message);
}
}try {
const status = await client.getChannelStatus('live-channel');
if (status.status === 'Live') {
// Handle active stream
} else {
// Handle idle channel
}
} catch (error) {
if (error.code === 'NoSuchLiveChannel') {
console.error('Channel does not exist');
} else if (error.code === 'ChannelNotLive') {
console.log('Channel is not currently streaming');
} else {
console.error('Status check failed:', error.message);
}
}// Use time-limited publish URLs
const securePublishUrl = client.getRtmpUrl('secure-channel', {
expires: 1800, // 30 minutes
params: {
'auth-token': generateSecureToken(),
'user-id': userId
}
});// Create VOD highlights after stream ends
async function createHighlights(channelId, streamStartTime, streamEndTime) {
const highlights = [
{ name: 'opening', start: streamStartTime, duration: 300 }, // First 5 minutes
{ name: 'peak', start: streamStartTime + 1800, duration: 600 }, // 30min mark, 10min clip
{ name: 'closing', start: streamEndTime - 300, duration: 300 } // Last 5 minutes
];
for (const highlight of highlights) {
await client.createVod(channelId, highlight.name, {
startTime: highlight.start,
endTime: highlight.start + highlight.duration
});
console.log(`Created ${highlight.name} highlight`);
}
}