Video Push Notifications
Keep your audience engaged with intelligent push notifications for live streams, broadcast events, and viewer interactions. Get notified when streams start, viewers join, or important stream events occur.
Overview
social.plus Video SDK provides comprehensive push notification capabilities specifically designed for live streaming applications. Support both direct delivery for quick implementation and webhook integration for custom notification processing.
Stream-Specific Notifications
- Stream Lifecycle - Start, end, and status change notifications
- Viewer Activity - Join, leave, and viewer count updates
- Broadcast Events - Connection issues, quality changes, and technical alerts
- Interactive Features - Chat messages, reactions, and viewer engagement
- Recording Status - Recording start, stop, and availability notifications
- Cross-platform Support - iOS, Android, React Native, Flutter, and Web
Notification Types
Stream Lifecycle Events
| Event | When Triggered | Default Message |
|---|
stream.started | Stream goes live | β is now live!β |
stream.ended | Stream stops | β stream has endedβ |
stream.scheduled | Scheduled stream reminder | β goes live in 15 minutesβ |
Viewer Activity
| Event | When Triggered | Default Message |
|---|
viewer.joined | New viewer joins | β joined the streamβ |
viewer.milestone | Viewer count milestones | βπ viewers watching!β |
viewer.follow | Viewer follows broadcaster | β followed youβ |
Broadcasting Alerts
| Event | When Triggered | Default Message |
|---|
broadcast.quality_low | Stream quality drops | βStream quality decreasedβ |
broadcast.reconnected | Connection restored | βStream connection restoredβ |
broadcast.error | Critical broadcast error | βStream encountered an errorβ |
Recording Events
| Event | When Triggered | Default Message |
|---|
recording.started | Recording begins | βRecording startedβ |
recording.completed | Recording ready | βYour stream recording is readyβ |
recording.failed | Recording error | βRecording failed to saveβ |
iOS
Android
React Native
Flutter
Web
Setup APNs for Video Notifications
- Configure APNs Certificate
import Social_Video
// Register for video-specific notifications
VideoNotificationManager.shared.register(for: [
.streamStarted,
.viewerJoined,
.broadcastAlert,
.recordingReady
])
- Handle Stream Notifications
// AppDelegate.swift
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
if let streamId = userInfo["stream_id"] as? String,
let eventType = userInfo["event_type"] as? String {
switch eventType {
case "stream.started":
// Navigate to live stream
navigateToStream(streamId)
case "viewer.joined":
// Update viewer count UI
updateViewerCount()
case "recording.completed":
// Show recording available
showRecordingAlert()
default:
break
}
}
}
- Custom Notification Handling
VideoNotificationManager.shared.configure { notification in
notification.sound = .default
notification.badge = 1
// Custom title based on stream type
if notification.streamType == "live" {
notification.title = "π΄ \(notification.broadcasterName) is LIVE"
}
return notification
}
Setup FCM for Video Notifications
- Configure Firebase Messaging
// VideoNotificationService.kt
class VideoNotificationService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
val streamId = remoteMessage.data["stream_id"]
val eventType = remoteMessage.data["event_type"]
when (eventType) {
"stream.started" -> handleStreamStarted(streamId)
"viewer.joined" -> handleViewerJoined(remoteMessage.data)
"broadcast.alert" -> handleBroadcastAlert(remoteMessage.data)
"recording.completed" -> handleRecordingReady(streamId)
}
}
private fun handleStreamStarted(streamId: String?) {
streamId?.let {
createStreamNotification(
title = "π΄ Live Stream Started",
body = "Tap to join the stream",
deepLink = "app://stream/$it"
)
}
}
}
- Create Rich Stream Notifications
private fun createStreamNotification(title: String, body: String, deepLink: String) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(deepLink))
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val notification = NotificationCompat.Builder(this, STREAM_CHANNEL_ID)
.setContentTitle(title)
.setContentText(body)
.setSmallIcon(R.drawable.ic_live_stream)
.setContentIntent(pendingIntent)
.addAction(R.drawable.ic_play, "Join Stream", pendingIntent)
.addAction(R.drawable.ic_share, "Share", createShareIntent())
.setAutoCancel(true)
.build()
notificationManager.notify(STREAM_NOTIFICATION_ID, notification)
}
Cross-platform Video Notifications
- Install Dependencies
npm install @react-native-async-storage/async-storage
npm install @react-native-community/push-notification-ios
npm install react-native-push-notification
- Configure Video Notifications
import { VideoNotifications } from '@social-plus/video-react-native';
// Initialize video notifications
VideoNotifications.configure({
onStreamStarted: (streamData) => {
// Navigate to live stream
navigation.navigate('LiveStream', { streamId: streamData.id });
},
onViewerActivity: (viewerData) => {
// Update viewer count
setViewerCount(viewerData.count);
},
onRecordingReady: (recordingData) => {
// Show recording notification
showRecordingAlert(recordingData.url);
}
});
- Handle Background Notifications
// Background notification handler
VideoNotifications.setBackgroundMessageHandler(async (remoteMessage) => {
const { stream_id, event_type, broadcaster_name } = remoteMessage.data;
switch (event_type) {
case 'stream.started':
await AsyncStorage.setItem('pending_stream', stream_id);
break;
case 'viewer.milestone':
// Store milestone for later display
await AsyncStorage.setItem('viewer_milestone', JSON.stringify(remoteMessage.data));
break;
}
});
Flutter Video Notifications
- Add Dependencies
dependencies:
firebase_messaging: ^14.6.5
flutter_local_notifications: ^15.1.0
social_plus_video: ^1.0.0
- Initialize Video Notifications
import 'package:social_plus_video/notifications.dart';
class VideoNotificationHandler {
static Future<void> initialize() async {
// Initialize Firebase Messaging
FirebaseMessaging messaging = FirebaseMessaging.instance;
// Configure video-specific handlers
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
_handleForegroundMessage(message);
});
FirebaseMessaging.onBackgroundMessage(_handleBackgroundMessage);
}
static void _handleForegroundMessage(RemoteMessage message) {
final streamId = message.data['stream_id'];
final eventType = message.data['event_type'];
switch (eventType) {
case 'stream.started':
_showStreamStartedNotification(message);
break;
case 'viewer.joined':
_updateViewerCount(message.data);
break;
}
}
static Future<void> _handleBackgroundMessage(RemoteMessage message) async {
// Handle background video notifications
await VideoNotificationService.handleBackgroundEvent(message);
}
}
- Custom Stream Notifications
static Future<void> _showStreamStartedNotification(RemoteMessage message) async {
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
const androidDetails = AndroidNotificationDetails(
'video_stream_channel',
'Video Stream Notifications',
channelDescription: 'Notifications for live stream events',
importance: Importance.high,
priority: Priority.high,
icon: '@drawable/ic_live_stream',
);
const iosDetails = DarwinNotificationDetails(
presentAlert: true,
presentBadge: true,
presentSound: true,
);
const details = NotificationDetails(
android: androidDetails,
iOS: iosDetails,
);
await flutterLocalNotificationsPlugin.show(
0,
'π΄ ${message.data['broadcaster_name']} is LIVE',
'Tap to join the stream',
details,
payload: message.data['stream_id'],
);
}
Web Video Notifications
- Service Worker Setup
// sw.js - Service Worker for background notifications
self.addEventListener('push', event => {
const data = event.data.json();
if (data.event_type === 'stream.started') {
const options = {
body: `${data.broadcaster_name} is now live!`,
icon: '/icons/live-stream-icon.png',
badge: '/icons/badge-icon.png',
tag: `stream-${data.stream_id}`,
data: { streamId: data.stream_id },
actions: [
{
action: 'join',
title: 'Join Stream',
icon: '/icons/play-icon.png'
},
{
action: 'share',
title: 'Share',
icon: '/icons/share-icon.png'
}
]
};
event.waitUntil(
self.registration.showNotification('π΄ Live Stream Started', options)
);
}
});
// Handle notification clicks
self.addEventListener('notificationclick', event => {
const { action, data } = event.notification;
if (action === 'join') {
event.waitUntil(
clients.openWindow(`/stream/${data.streamId}`)
);
}
event.notification.close();
});
- Register for Video Notifications
import { VideoNotificationManager } from '@social-plus/video-web';
class VideoNotifications {
static async initialize() {
// Request notification permission
const permission = await Notification.requestPermission();
if (permission === 'granted') {
// Register service worker
const registration = await navigator.serviceWorker.register('/sw.js');
// Subscribe to video notifications
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: this.getVapidKey()
});
// Configure video-specific events
VideoNotificationManager.subscribe({
subscription,
events: ['stream.started', 'viewer.milestone', 'recording.ready']
});
}
}
static handleStreamNotification(notification) {
// Handle in-app notifications when page is visible
if (document.visibilityState === 'visible') {
this.showInAppNotification(notification);
}
}
}
Webhook Integration
For advanced customization, integrate with webhooks to process stream events before sending notifications:
// Webhook endpoint handler
app.post('/video-webhooks', (req, res) => {
const { event_type, stream_id, data } = req.body;
switch (event_type) {
case 'stream.started':
// Custom logic for stream start
sendCustomStreamNotification(stream_id, data);
break;
case 'viewer.milestone':
// Celebrate viewer milestones
if (data.viewer_count % 100 === 0) {
sendMilestoneNotification(stream_id, data.viewer_count);
}
break;
case 'recording.completed':
// Process recording completion
processRecordingNotification(stream_id, data.recording_url);
break;
}
res.status(200).send('OK');
});
Configuration Options
Configure notification behavior and appearance:
Notification Settings
User Preferences
Stream-Specific Settings
// Global video notification configuration
VideoNotifications.configure({
// Delivery settings
directPush: true,
webhookUrl: 'https://your-server.com/video-webhooks',
// Event subscriptions
events: {
streamStarted: true,
streamEnded: true,
viewerJoined: false, // Disable viewer join notifications
viewerMilestone: true,
recordingReady: true,
broadcastAlerts: true
},
// Notification appearance
appearance: {
showBroadcasterAvatar: true,
useStreamThumbnail: true,
showViewerCount: true,
customSound: 'stream_notification.wav'
},
// Timing settings
timing: {
scheduleReminder: 15, // Minutes before scheduled stream
quietHours: {
start: '22:00',
end: '08:00'
}
}
});
// User-level notification preferences
const userPreferences = {
streamNotifications: true,
viewerUpdates: false,
recordingAlerts: true,
broadcastIssues: true,
// Specific broadcasters
followedBroadcasters: {
'broadcaster-123': {
streamStarted: true,
scheduleReminders: true
}
},
// Delivery preferences
deliveryMethods: {
push: true,
email: false,
inApp: true
}
};
await VideoNotifications.updateUserPreferences(userId, userPreferences);
// Configure notifications per stream
await VideoNotifications.configureStream(streamId, {
notifyOnStart: true,
notifyOnEnd: false,
viewerMilestones: [50, 100, 500, 1000],
recordingNotifications: true,
// Target audience
audience: {
followers: true,
subscribers: true,
inviteOnly: false
},
// Custom message templates
templates: {
streamStarted: "π΄ {broadcaster} is live with: {title}",
viewerMilestone: "π {count} people are watching {broadcaster}!"
}
});
Testing & Debugging
Test Notifications
Debug Information
// Test video notifications in development
VideoNotifications.test({
event: 'stream.started',
streamId: 'test-stream-123',
broadcasterName: 'Test Broadcaster',
title: 'Test Stream Title',
thumbnail: 'https://example.com/thumbnail.jpg'
});
// Test specific platforms
VideoNotifications.testPlatform('ios', {
deviceToken: 'test-device-token',
event: 'viewer.milestone',
data: { viewerCount: 100 }
});
// Enable debug logging
VideoNotifications.setDebugMode(true);
// Check notification delivery status
const status = await VideoNotifications.getDeliveryStatus(notificationId);
console.log('Delivery Status:', status);
// Monitor notification events
VideoNotifications.on('notification.sent', (data) => {
console.log('Notification sent:', data);
});
VideoNotifications.on('notification.failed', (error) => {
console.error('Notification failed:', error);
});
Best Practices
Stream Timing: Send stream start notifications immediately but batch viewer activity updates to avoid overwhelming users.
Notification Strategy
- Stream Lifecycle - Always notify for stream start/end events
- Viewer Activity - Use milestones instead of individual join/leave events
- Recording Status - Critical for content creators who rely on recordings
- Broadcast Issues - Essential for broadcasters to maintain stream quality
User Experience
- Permission Timing - Request during onboarding or first stream creation
- Relevance - Only notify followers/subscribers of broadcaster
- Frequency - Respect quiet hours and user preferences
- Content - Include stream thumbnail and viewer count when possible
Technical Considerations
- Delivery Speed - Stream notifications should be near real-time
- Fallback - Use webhook for web notifications when push isnβt available
- Retry Logic - Implement retry for failed critical notifications
- Analytics - Track notification open rates and stream conversion
| Platform | Direct Push | Webhooks | Rich Media | Actions | Background |
|---|
| iOS | β
APNs | β
| β
Images | β
Join/Share | β
|
| Android | β
FCM | β
| β
Images | β
Join/Share | β
|
| React Native | β
| β
| β
Images | β
Custom | β
|
| Flutter | β
| β
| β
Images | β
Custom | β
|
| Web | β | β
| β
Images | β
Join/Share | β
Service Worker |
Next Steps
- Stream Events - Implement comprehensive stream event handling
- Broadcasting Setup - Configure broadcasting with notifications
- Platform Guides: Configure per platform:
- Troubleshooting - Common notification issues
Production Checklist: Ensure APNs/FCM certificates are configured, webhook endpoints are secured with HTTPS, and notification permissions are properly requested before going live.