Video-Anschluss
Mit der Python-Bibliothek Vonage Video Connector können Sie programmatisch an Vonage Video API-Sitzungen teilnehmen als serverseitiger Teilnehmer teilzunehmen. Diese Bibliothek ermöglicht es Ihnen, sich mit Videositzungen zu verbinden, Streams zu veröffentlichen und zu abonnieren sowie die Verarbeitung von Audio- und Videodaten in Echtzeit.
Die Bibliothek übernimmt automatisch die WebRTC-Konnektivität, die Medienverarbeitung und die Sitzungsverwaltung, so dass Sie sich auf die Entwicklung Ihrer Anwendungslogik konzentrieren können. auf die Entwicklung Ihrer Anwendungslogik konzentrieren können. Audio wird als lineare PCM 16-Bit-Daten und Video als 8-Bit-Frames in den Formaten YUV420P, RGB24 oder ARGB32 geliefert, und zwar mit konfigurierbaren Abtastraten, Auflösungen und Kanalkonfigurationen.
Wichtig Die Python-Bibliothek des Vonage Video Connectors ist für serverseitige Anwendungen konzipiert und erfordert gültige Vonage Video API-Anmeldedaten und Token mit entsprechenden Berechtigungen.
Dieses Thema umfasst die folgenden Abschnitte:
- Private Beta
- Anforderungen
- Datenstrukturen
- Verbinden mit einer Sitzung
- Einstellungen der Sitzung
- Veröffentlichung von Datenströmen
- Abonnieren von Streams
- Verarbeitung von Audiodaten
- Verarbeitung von Videodaten
- Verwaltung der Medienpuffer
- Ereignis-Rückrufe
Private Beta
Vonage Video Connector befindet sich in der Betaphase. Kontaktieren Sie uns, um frühen Zugang zu erhalten.
Anforderungen
Diese Bibliothek erfordert Python 3.13 auf Linux AMD64 und ARM64 Plattformen. Wir empfehlen die Verwendung von Debian Bookworm, da dies die Distribution ist, in der sie am gründlichsten getestet wurde.
Datenstrukturen
Die Vonage Video Connector Python-Bibliothek verwendet mehrere wichtige Datenstrukturen, um Sitzungen, Verbindungen, Streams und Audiodaten darzustellen. Das Verständnis dieser Strukturen ist für die effektive Arbeit mit der Bibliothek unerlässlich.
Sitzung
Stellt eine Vonage Video API-Sitzung dar, mit der sich Clients verbinden können:
from vonage_video_connector.models import Session
# Session object properties
session.id # str: Unique identifier for the session
Die Session Objekt wird an verschiedene Callback-Funktionen übergeben, um festzustellen, welche Sitzung das Ereignis ausgelöst hat.
Verbindung
Stellt die Verbindung eines Teilnehmers zu einer Sitzung dar:
from vonage_video_connector.models import Connection
# Connection object properties
connection.id # str: Unique identifier for the connection
connection.creation_time # datetime: When the connection was established
connection.data # str: Connection data (encoded in the token)
Verbindungsdaten können verwendet werden, um benutzerdefinierte Metadaten über Teilnehmer zu speichern, z. B. Benutzer-IDs oder Rollen.
Stream
Stellt einen Medienstrom (Audio/Video) dar, der von einem Teilnehmer veröffentlicht wurde:
from vonage_video_connector.models import Stream
# Stream object properties
stream.id # str: Unique identifier for the stream
stream.connection # Connection: The underlying connection that published this stream
Streams werden erstellt, wenn Teilnehmer Medien veröffentlichen, und dienen zum Abonnieren ihrer Audio-/Videodaten.
Herausgeber
Stellt Ihren veröffentlichten Stream in der Sitzung dar:
from vonage_video_connector.models import Publisher
# Publisher object properties
publisher.stream # Stream: The underlying stream for this publisher
Die Publisher Objekt wird in verlagsbezogenen Callbacks verwendet und stellt Ihren eigenen veröffentlichten Medienstrom dar.
Abonnent
Stellt ein Abonnement für den Stream eines anderen Teilnehmers dar:
from vonage_video_connector.models import Subscriber
# Subscriber object properties
subscriber.stream # Stream: The underlying stream for this subscriber
Die Subscriber Objekt wird in abonnentenbezogenen Rückrufen verwendet und stellt Ihr Abonnement für den Empfang der Medien eines anderen Teilnehmers dar.
AudioDaten
Stellt die gesendeten oder empfangenen Audiodaten dar:
from vonage_video_connector.models import AudioData
# AudioData object properties
audio_data.sample_buffer # memoryview: 16-bit signed integer audio samples
audio_data.sample_rate # int: Sample rate (8000-48000 Hz)
audio_data.number_of_channels # int: 1 (mono) or 2 (stereo)
audio_data.number_of_frames # int: Number of audio frames
Anforderungen an das Audioformat:
- Probenpuffer muss 16-Bit-Ganzzahlen mit Vorzeichen enthalten
- Gültige Abtastraten: 8000, 12000, 16000, 24000, 32000, 44100, 48000 Hz
- Kanäle: 1 (Mono) oder 2 (Stereo)
- Die Puffergröße muss passen:
number_of_frames * number_of_channelsProben
VideoFrame
Stellt die gesendeten oder empfangenen Videobilddaten dar:
from vonage_video_connector.models import VideoFrame, VideoResolution
# VideoFrame object properties
video_frame.frame_buffer # memoryview: 8-bit unsigned char video frame data
video_frame.resolution # VideoResolution: Width and height in pixels
video_frame.format # str: Video format (YUV420P, RGB24, or ARGB32)
Anforderungen an das Videoformat:
- Rahmenpuffer muss 8-Bit-Zeichen ohne Vorzeichen enthalten
- Gültige Formate: YUV420P, RGB24 (BGR), ARGB32 (BGRA)
- Maximale Auflösung: 1920x1080 Pixel (2.073.600 Pixel insgesamt)
- Die Puffergröße variiert je nach Format und Auflösung
VideoAuflösung
Stellt die Abmessungen eines Videobildes dar:
from vonage_video_connector.models import VideoResolution
# VideoResolution object properties
resolution = VideoResolution(
width=640, # int: Width in pixels
height=480 # int: Height in pixels
)
MediaBufferStats
Liefert Statistiken über Medienpuffer:
from vonage_video_connector.models import MediaBufferStats, AudioBufferStats, VideoBufferStats
# MediaBufferStats object properties
stats.audio # Optional[AudioBufferStats]: Audio buffer statistics
stats.video # Optional[VideoBufferStats]: Video buffer statistics
# AudioBufferStats properties
stats.audio.duration # timedelta: Duration of queued audio
# VideoBufferStats properties
stats.video.duration # timedelta: Duration of queued video
Konfiguration der Strukturen
SessionSettings
Konfiguriert das Verhalten auf Sitzungsebene:
from vonage_video_connector.models import SessionSettings
session_settings = SessionSettings(
enable_migration=False, # bool: Enable automatic session migration
av=av_settings, # Optional[SessionAVSettings]: Audio/video configuration
logging=logging_settings # Optional[LoggingSettings]: Logging configuration
)
SessionAVSettings
Konfiguriert die Audio- und Videoeinstellungen für die Sitzung:
from vonage_video_connector.models import SessionAVSettings, SessionAudioSettings, SessionVideoPublisherSettings
av_settings = SessionAVSettings(
audio_publisher=SessionAudioSettings(sample_rate=48000, number_of_channels=2),
audio_subscribers_mix=SessionAudioSettings(sample_rate=48000, number_of_channels=1),
video_publisher=SessionVideoPublisherSettings(
resolution=VideoResolution(width=1280, height=720),
fps=30,
format="YUV420P"
)
)
Verstehen der Audiokonfiguration:
Die SessionAVSettings ermöglicht es Ihnen, verschiedene Audioformate für die Veröffentlichung und den Empfang zu konfigurieren:
audio_verlag: Definiert das Format für Audiodaten, die Sie über
add_audio(). Die gesendeten Audiodaten müssen mit der Samplerate und der Anzahl der Kanäle dieser Konfiguration übereinstimmen.audio_abonnenten_mix: Legt das Format für das gemischte Audio fest, das Sie von allen abonnierten Streams über den
on_audio_data_cbRückruf. Die Bibliothek übernimmt automatisch das Mischen der Audiodaten mehrerer Teilnehmer und die Neuabtastung/Kanalumwandlung in das von Ihnen angegebene Format.
Diese Trennung ermöglicht Ihnen die Optimierung für Ihren Anwendungsfall. Zum Beispiel:
- Veröffentlichen Sie in Stereo (2 Kanäle) für eine qualitativ hochwertige Ausgabe, während Sie eine Mono-Mischung (1 Kanal) erhalten, um die Verarbeitung zu vereinfachen.
- Veröffentlichung mit 16 kHz für Sprache und Empfang mit 48 kHz für High-Fidelity-Wiedergabe
- Verwenden Sie je nach den Anforderungen Ihrer Audioverarbeitungspipeline unterschiedliche Abtastraten für Veröffentlichung und Abonnement
SessionAudioSettings
Konfiguriert das Audioformat für die Veröffentlichung oder den Empfang von Audiodaten:
from vonage_video_connector.models import SessionAudioSettings
audio_settings = SessionAudioSettings(
sample_rate=48000, # int: Sample rate (8000-48000 Hz)
number_of_channels=1 # int: Channels - 1 (mono) or 2 (stereo)
)
SessionVideoPublisherSettings
Konfiguriert die Videoeinstellungen für die Veröffentlichung:
from vonage_video_connector.models import SessionVideoPublisherSettings, VideoResolution
video_settings = SessionVideoPublisherSettings(
resolution=VideoResolution(width=1280, height=720), # Resolution in pixels
fps=30, # int: Frames per second (1-30)
format="YUV420P" # str: Video format (YUV420P, RGB24, or ARGB32)
)
LoggingSettings
Steuert die Ausführlichkeit der Protokollierung:
from vonage_video_connector.models import LoggingSettings
logging_settings = LoggingSettings(
level="INFO" # str: ERROR, WARN, INFO, DEBUG, or TRACE
)
PublisherSettings
Konfiguriert Ihren veröffentlichten Stream:
from vonage_video_connector.models import PublisherSettings, PublisherAudioSettings
publisher_settings = PublisherSettings(
name="My Application", # str: Name for your published stream (required, min 1 char)
has_audio=True, # bool: Whether to publish audio
has_video=True, # bool: Whether to publish video
audio_settings=audio_settings # Optional[PublisherAudioSettings]: Audio configuration
)
Anmerkung: Mindestens eine der has_audio oder has_video muss sein True.
PublisherAudioSettings
Konfiguriert die Audioeinstellungen für Ihren veröffentlichten Stream:
from vonage_video_connector.models import PublisherAudioSettings
audio_settings = PublisherAudioSettings(
enable_stereo_mode=True, # bool: Publish in stereo (True) or mono (False)
enable_opus_dtx=False # bool: Enable discontinuous transmission
)
Diskontinuierliche Übertragung (DTX) sendet bei Stille keine Audiopakete mehr, um Bandbreite zu sparen.
SubscriberSettings
Konfiguriert das Teilnehmerverhalten:
from vonage_video_connector.models import SubscriberSettings, SubscriberVideoSettings, VideoResolution
subscriber_settings = SubscriberSettings(
subscribe_to_audio=True, # bool: Whether to subscribe to audio
subscribe_to_video=True, # bool: Whether to subscribe to video
video_settings=SubscriberVideoSettings(
preferred_resolution=VideoResolution(width=640, height=480),
preferred_framerate=15
)
)
Anmerkung: Mindestens eine der subscribe_to_audio oder subscribe_to_video muss sein True.
SubscriberVideoSettings
Konfiguriert die Videoeinstellungen für Abonnenten:
from vonage_video_connector.models import SubscriberVideoSettings, VideoResolution
video_settings = SubscriberVideoSettings(
preferred_resolution=VideoResolution(width=640, height=480), # Optional
preferred_framerate=15 # Optional: Preferred FPS (1-30)
)
Verstehen der bevorzugten Einstellungen:
Beim Abonnieren von gerouteten Streams, die Simulcast verwenden, kann die Vonage Video API SFU (Selective Forwarding Unit) verschiedene Qualitätsebenen des Videos senden. Die preferred_resolution und preferred_framerate Einstellungen können Sie eine bestimmte Qualitätsebene anfordern:
- bevorzugte_Auflösung: Fordert eine bestimmte räumliche Ebene (Auflösung) an. Die SFU sendet die Ebene, die Ihrer Präferenz am ehesten entspricht.
- bevorzugte_framerate: Fordert eine bestimmte zeitliche Ebene (Bildrate) an. Die SFU sendet die Ebene, die Ihrer Präferenz am ehesten entspricht.
Diese Einstellungen tragen dazu bei, die Bandbreitennutzung und die Verarbeitungsanforderungen auf der Teilnehmerseite zu optimieren, indem nur die benötigte Qualitätsstufe angefordert wird, anstatt immer die höchste verfügbare Qualität zu erhalten.
Beziehungen zwischen Datenstrukturen
Die Datenstrukturen stehen in der folgenden Hierarchie zueinander:
Session
├── Connection (multiple participants)
│ └── Stream (participant's published media)
│ ├── Publisher (your published stream)
│ └── Subscriber (your subscription to their stream)
├── AudioData (flowing through streams)
└── VideoFrame (flowing through streams)
Verbinden mit einer Sitzung
Grundlegende Verbindung
Um eine Verbindung zu einer Vonage Video API-Sitzung herzustellen, benötigen Sie Ihre Anwendungs-ID (API-Schlüssel bei Verwendung von Tokbox), die Sitzungs-ID und ein gültiges Token:
from vonage_video_connector import VonageVideoClient
from vonage_video_connector.models import SessionSettings, SessionAudioSettings, LoggingSettings
# Create client instance
client = VonageVideoClient()
# Configure session settings
session_settings = SessionSettings(
enable_migration=False,
av=SessionAVSettings(
audio_subscribers_mix=SessionAudioSettings(
sample_rate=48000,
number_of_channels=1
)
),
logging=LoggingSettings(level="INFO")
)
# Connect to session
success = client.connect(
application_id="your_application_id",
session_id="your_session_id",
token="your_token",
session_settings=session_settings,
on_connected_cb=on_session_connected,
on_error_cb=on_session_error
)
Verbindung mit allen Rückrufen
Für eine vollständige Sitzungsverwaltung müssen alle verfügbaren Rückrufe implementiert werden:
success = client.connect(
application_id="your_application_id",
session_id="your_session_id",
token="your_token",
session_settings=session_settings,
on_error_cb=on_session_error,
on_connected_cb=on_session_connected,
on_disconnected_cb=on_session_disconnected,
on_connection_created_cb=on_connection_created,
on_connection_dropped_cb=on_connection_dropped,
on_stream_received_cb=on_stream_received,
on_stream_dropped_cb=on_stream_dropped,
on_audio_data_cb=on_audio_data,
on_ready_for_audio_cb=on_ready_for_audio,
on_media_buffer_drained_cb=on_media_buffer_drained
)
Trennen der Verbindung zu einer Sitzung
Trennen Sie die Verbindung, wenn die Sitzung beendet ist:
success = client.disconnect()
Einstellungen der Sitzung
Audio- und Videokonfiguration
Konfigurieren Sie die Audio- und Videoeinstellungen für die Sitzung, um das Format der Mediendaten zu steuern:
from vonage_video_connector.models import (
SessionAVSettings,
SessionAudioSettings,
SessionVideoPublisherSettings,
VideoResolution
)
# Configure audio for publisher and subscriber mix
audio_publisher = SessionAudioSettings(
sample_rate=48000, # Valid: 8000, 12000, 16000, 24000, 32000, 44100, 48000
number_of_channels=2 # 1 for mono, 2 for stereo
)
audio_subscribers_mix = SessionAudioSettings(
sample_rate=48000,
number_of_channels=1
)
# Configure video publisher settings
video_publisher = SessionVideoPublisherSettings(
resolution=VideoResolution(width=1280, height=720),
fps=30,
format="YUV420P" # Valid: YUV420P, RGB24, ARGB32
)
# Combine into session AV settings
av_settings = SessionAVSettings(
audio_publisher=audio_publisher,
audio_subscribers_mix=audio_subscribers_mix,
video_publisher=video_publisher
)
Konfiguration der Protokollierung
Steuern Sie die Ausführlichkeit der Konsolenprotokollierung:
from vonage_video_connector.models import LoggingSettings
# Configure logging level
logging_settings = LoggingSettings(
level="DEBUG" # Valid: ERROR, WARN, INFO, DEBUG, TRACE
)
Migration von Sitzungen
Aktivieren Sie die automatische Sitzungsmigration im Falle einer SFU-Rotation:
from vonage_video_connector.models import SessionSettings
session_settings = SessionSettings(
enable_migration=True, # Enable automatic migration
av=av_settings,
logging=logging_settings
)
Veröffentlichung von Datenströmen
Konfiguration des Herausgebers
Konfigurieren Sie die Publisher-Einstellungen, bevor Sie mit der Veröffentlichung beginnen:
from vonage_video_connector.models import PublisherSettings, PublisherAudioSettings
# Configure publisher audio settings
audio_settings = PublisherAudioSettings(
enable_stereo_mode=True, # Publish in stereo
enable_opus_dtx=False # Enable discontinuous transmission for bandwidth savings
)
# Create publisher settings for audio and video
publisher_settings = PublisherSettings(
name="AI Assistant Bot",
has_audio=True,
has_video=True,
audio_settings=audio_settings
)
# Or audio-only publisher
audio_only_settings = PublisherSettings(
name="Audio Bot",
has_audio=True,
has_video=False,
audio_settings=audio_settings
)
Veröffentlichung beginnen
Beginn der Veröffentlichung eines Streams in der Sitzung:
success = client.publish(
settings=publisher_settings,
on_error_cb=on_publisher_error,
on_stream_created_cb=on_stream_created,
on_stream_destroyed_cb=on_stream_destroyed
)
Important:
If you're publishing audio (has_audio=True), you must wait for the on_ready_for_audio_cb callback to be invoked before calling add_audio(). This callback indicates that the audio system is initialized and ready to accept audio data. This requirement does not apply to video-only publishing scenarios.
# Example: Wait for audio system to be ready
audio_ready = False
def on_ready_for_audio(session):
global audio_ready
audio_ready = True
print("Audio system ready - can now add audio")
# Connect with the callback
client.connect(
application_id="your_application_id",
session_id="your_session_id",
token="your_token",
session_settings=session_settings,
on_ready_for_audio_cb=on_ready_for_audio
)
# Publish
client.publish(settings=publisher_settings)
# Wait for audio to be ready before adding audio
while not audio_ready:
time.sleep(0.01)
# Now safe to add audio
client.add_audio(audio_data)
Hinzufügen von Audiodaten
Senden Sie Audiodaten an Ihren veröffentlichten Stream:
from vonage_video_connector.models import AudioData
# Create audio data (example with 16-bit PCM samples)
audio_buffer = memoryview(your_audio_samples) # Must be 16-bit signed integers
audio_data = AudioData(
sample_buffer=audio_buffer,
sample_rate=48000,
number_of_channels=1,
number_of_frames=960 # 20ms at 48kHz
)
# Add audio to the published stream
success = client.add_audio(audio_data)
Veröffentlichung stoppen
Beenden Sie die Veröffentlichung, wenn Sie fertig sind:
success = client.unpublish()
Abonnieren von Streams
Streams abonnieren
Wenn ein neuer Stream empfangen wird, abonnieren Sie ihn, um Audio- und/oder Videodaten zu empfangen:
from vonage_video_connector.models import SubscriberSettings, SubscriberVideoSettings, VideoResolution
def on_stream_received(session, stream):
print(f"New stream received: {stream.id}")
print(f"From connection: {stream.connection.id}")
# Configure subscriber settings (optional)
subscriber_settings = SubscriberSettings(
subscribe_to_audio=True,
subscribe_to_video=True,
video_settings=SubscriberVideoSettings(
preferred_resolution=VideoResolution(width=640, height=480),
preferred_framerate=15
)
)
# Subscribe to the stream
success = client.subscribe(
stream=stream,
settings=subscriber_settings,
on_error_cb=on_subscriber_error,
on_connected_cb=on_subscriber_connected,
on_disconnected_cb=on_subscriber_disconnected,
on_render_frame_cb=on_render_frame
)
Empfang von abonnierten Medien
Wenn Sie Streams abonnieren, liefert die Bibliothek Audio- und Videodaten über verschiedene Callbacks:
Video-Daten: Die Videobilder werden einzeln pro abonniertem Stream über die on_render_frame_cb Rückruf. Jeder Callback-Aufruf enthält die subscriber Objekt, das angibt, zu welchem Stream das Videobild gehört. So können Sie Videos von verschiedenen Teilnehmern getrennt verarbeiten.
def on_render_frame(subscriber, video_frame):
"""Called for each subscribed stream's video frames"""
stream_id = subscriber.stream.id
width = video_frame.resolution.width
height = video_frame.resolution.height
print(f"Video frame from stream {stream_id}: {width}x{height}")
# Process video for this specific stream
Audio-Daten: Audio wird als ein einziger gemischter Stream über die on_audio_data_cb Callback registriert während connect(). Die Bibliothek mischt automatisch die Audiosignale aller abonnierten Streams zu einem einzigen Audiostrom zusammen. Sie können bei diesem Rückruf nicht zwischen den Audios der einzelnen Teilnehmer unterscheiden.
def on_audio_data(session, audio_data):
"""Called with mixed audio from all subscribed streams"""
sample_rate = audio_data.sample_rate
channels = audio_data.number_of_channels
print(f"Mixed audio from all subscribers: {sample_rate}Hz, {channels} channel(s)")
# Process the combined audio from all participants
Dieses Design ermöglicht es Ihnen:
- Verarbeiten Sie die Videos der einzelnen Teilnehmer unabhängig voneinander für Aufgaben wie Layout-Verwaltung, Einzelaufzeichnung oder Videoeffekte pro Stream
- Empfangen Sie vorgemischte Audiodaten, die für die Wiedergabe oder Weiterverarbeitung ohne manuelles Mischen optimiert sind.
- Konfigurieren Sie das gemischte Audioformat über
audio_subscribers_mixinSessionAVSettingsentsprechend Ihren Verarbeitungsanforderungen
Abbestellen von Streams
Beenden Sie den Empfang von Medien aus einem bestimmten Stream:
def on_stream_dropped(session, stream):
print(f"Stream dropped: {stream.id}")
# Unsubscribe from the stream
success = client.unsubscribe(stream)
Verarbeitung von Audiodaten
Audioformat
Die Audiodaten werden als lineare PCM-Ganzzahlen mit 16 Bit und Vorzeichen mit den folgenden Eigenschaften geliefert:
- Musterpreise8000, 12000, 16000, 24000, 32000, 44100, oder 48000 Hz
- Kanäle: 1 (Mono) oder 2 (Stereo)
- Format: 16-Bit-Ganzzahlen mit Vorzeichen in einer
memoryviewPuffer - Rahmengröße: In der Regel 20ms-Blöcke (variiert je nach Abtastrate)
Verarbeitung von Audiodaten
Behandeln Sie eingehende Audiodaten im Audiodaten-Callback:
def on_audio_data(session, audio_data):
"""Process incoming audio data from subscribed streams"""
# Access audio properties
sample_rate = audio_data.sample_rate
channels = audio_data.number_of_channels
frames = audio_data.number_of_frames
# Access the audio buffer (memoryview of 16-bit signed integers)
audio_buffer = audio_data.sample_buffer
print(f"Received {frames} frames at {sample_rate}Hz, {channels} channel(s)")
# Convert to bytes if needed
audio_bytes = audio_buffer.tobytes()
# Process the audio (e.g., transcription, analysis, etc.)
process_audio(audio_buffer, sample_rate, channels)
# Generate response audio and add it back
response_audio = generate_response(audio_buffer)
if response_audio:
client.add_audio(response_audio)
Erstellen von Audiodaten
Erstellen Sie beim Hinzufügen von Audio ordnungsgemäß formatierte AudioData Objekte:
import array
# Create 16-bit PCM audio samples (example: sine wave)
sample_rate = 48000
duration_ms = 20 # 20ms frame
num_samples = int(sample_rate * duration_ms / 1000)
# Generate audio samples as 16-bit signed integers
samples = array.array('h') # 'h' = signed short (16-bit)
for i in range(num_samples):
# Example: generate a 440Hz sine wave
sample = int(32767 * 0.5 * math.sin(2 * math.pi * 440 * i / sample_rate))
samples.append(sample)
# Create AudioData object
audio_data = AudioData(
sample_buffer=memoryview(samples),
sample_rate=sample_rate,
number_of_channels=1,
number_of_frames=num_samples
)
# Add the audio
client.add_audio(audio_data)
Kontinuität der Audiodaten
Bei der Veröffentlichung von Audiodateien verwaltet die Bibliothek in verschiedenen Szenarien automatisch die Kontinuität der Audiodateien:
Erstveröffentlichung:
Wenn Sie mit der Veröffentlichung von Audio (über publish() mit has_audio=True), sendet die Bibliothek automatisch Stille (mit Null gefüllte Audio-Frames), bis Sie Ihre ersten Audiodaten über add_audio(). Dadurch wird sichergestellt, dass der Audiostream den Teilnehmern sofort zur Verfügung steht, ohne dass Sie darauf warten müssen, dass Ihre Anwendung Audiodaten erzeugt.
Schweigetoleranz:
Wenn Sie die Bereitstellung von Audiodaten über add_audio()toleriert die Bibliothek kurze Lücken, indem sie keine Audiopakete sendet. Diese Hystereseperiode verhindert unnötige Stille-Pakete während kurzzeitiger Verarbeitungsverzögerungen.
Ausdrückliches Schweigen: Wenn nach Ablauf der Toleranzzeit keine neuen Audiodaten verfügbar sind, schaltet die Bibliothek auf das Senden expliziter Stille-Frames um (Audio mit Null-Füllung). Dadurch wird der Audiostrom beibehalten, während gleichzeitig angezeigt wird, dass kein aktives Audio bereitgestellt wird.
Pufferspülung: Wenn Sie weniger als eine volle Periode an Audiodaten zur Verfügung stellen, spült die Bibliothek die verbleibenden Daten und füllt sie mit Stille auf, um das korrekte Timing beizubehalten und einen Audiodrift zu verhindern.
Bewährte Praktiken:
- Behalten Sie eine konsistente Audiorate bei, indem Sie
add_audio()in regelmäßigen Abständen entsprechend der eingestellten Abtastrate - Pufferstatistiken überwachen mit
get_media_buffer_stats()um angemessene Audiodaten zu gewährleisten - Behandeln Sie die
on_media_buffer_drained_cbCallback, um zu erkennen, wenn der Audiopuffer erschöpft ist - Erwägen Sie die Implementierung einer Audiogenerierungsstrategie, die sich an unterschiedliche Verarbeitungslasten anpasst
Dieses automatische Audiomanagement stellt sicher, dass Ihr veröffentlichter Audiostream auch bei vorübergehenden Lücken in der Datenverfügbarkeit kontinuierlich und zeitlich korrekt bleibt.
Verarbeitung von Videodaten
Video-Format
Die Videodaten werden als 8-Bit-Zeichen ohne Vorzeichen in einem von drei Formaten geliefert:
- YUV420P: Planares YUV-Format mit 4:2:0 Chroma-Unterabtastung
- RGB2424-Bit-BGR-Format (8 Bit pro Kanal)
- ARGB32: 32-Bit BGRA-Format mit Alphakanal
Video-Spezifikationen:
- Entschließungen: Bis zu 1920x1080 (Full HD)
- Bildfrequenzen: 1-30 FPS
- Format: 8-Bit-Zeichen ohne Vorzeichen in einem
memoryviewPuffer
Verarbeitung von Videobildern
Behandelt eingehende Videobilder im Rendering-Frame-Callback:
def on_render_frame(subscriber, video_frame):
"""Process incoming video frames from subscribed streams"""
# Access video properties
width = video_frame.resolution.width
height = video_frame.resolution.height
format = video_frame.format
# Access the video buffer (memoryview of 8-bit unsigned chars)
frame_buffer = video_frame.frame_buffer
print(f"Received {width}x{height} frame in {format} format")
# Convert to bytes if needed
frame_bytes = frame_buffer.tobytes()
# Process the video frame (e.g., computer vision, recording, etc.)
process_video(frame_buffer, width, height, format)
Erstellen von Videobildern
Wenn Sie ein Video veröffentlichen, erstellen Sie richtig formatierte VideoFrame Objekte:
import array
from vonage_video_connector.models import VideoFrame, VideoResolution
# Create a video frame (example: solid color in YUV420P format)
width = 640
height = 480
# YUV420P format calculation:
# Y plane: width * height
# U plane: (width/2) * (height/2)
# V plane: (width/2) * (height/2)
y_size = width * height
uv_size = (width // 2) * (height // 2)
total_size = y_size + 2 * uv_size
# Create frame buffer as 8-bit unsigned chars
frame_data = array.array('B', [128] * total_size) # 'B' = unsigned char (8-bit)
# Create VideoFrame object
video_frame = VideoFrame(
frame_buffer=memoryview(frame_data),
resolution=VideoResolution(width=width, height=height),
format="YUV420P"
)
# Add the video frame
client.add_video(video_frame)
Kontinuität der Videobilder
Wenn Sie ein Video veröffentlichen, verwaltet die Bibliothek die Bildkontinuität in verschiedenen Szenarien automatisch:
Erstveröffentlichung:
Wenn Sie mit der Veröffentlichung von Videos beginnen (über publish() mit has_video=True), sendet die Bibliothek automatisch schwarze Bilder, bis Sie Ihr erstes Bild über add_video(). Dadurch wird sichergestellt, dass der Videostream den Abonnenten sofort zur Verfügung steht, ohne dass Sie darauf warten müssen, dass Ihre Anwendung Videodaten erzeugt.
Wiederholung des letzten Bildes:
Wenn Sie die Bereitstellung von Videobildern über add_video()wählen, wird die Bibliothek automatisch das letzte von Ihnen bereitgestellte Bild wiederholen. Dies gewährleistet eine reibungslose Wiedergabe für die Abonnenten ohne Unterbrechung. Das letzte Bild wird bis zu 2 Sekunden lang wiederholt.
Schwarzer Fallback-Rahmen: Nach der maximalen Wiederholungszeit (2 Sekunden) schaltet die Bibliothek auf die Veröffentlichung schwarzer Bilder um. Dies zeigt den Abonnenten an, dass keine Videodaten mehr aktiv bereitgestellt werden, während der Videostream aufrechterhalten wird.
Bewährte Praktiken:
- Behalten Sie eine konstante Bildrate bei, indem Sie
add_video()in regelmäßigen Abständen entsprechend Ihrer konfigurierten FPS - Pufferstatistiken überwachen mit
get_media_buffer_stats()um ausreichende Videodaten zu gewährleisten - Behandeln Sie die
on_media_buffer_drained_cbCallback, um zu erkennen, wenn der Videopuffer erschöpft ist - Erwägen Sie die Implementierung einer Strategie zur Generierung von Frames, die sich an unterschiedliche Verarbeitungslasten anpasst.
Diese automatische Bildverwaltung stellt sicher, dass Ihr veröffentlichter Videostream auch bei vorübergehenden Lücken in der Datenverfügbarkeit kontinuierlich bleibt.
Verwaltung der Medienpuffer
Überprüfung der Pufferstatistik
Überwachen Sie den Zustand Ihrer Medienpuffer:
# Get current buffer statistics
stats = client.get_media_buffer_stats()
if stats.audio:
print(f"Audio buffer duration: {stats.audio.duration.total_seconds()}s")
if stats.video:
print(f"Video buffer duration: {stats.video.duration.total_seconds()}s")
Löschen von Medienpuffern
Löschen Sie bei Bedarf sowohl Audio- als auch Videopuffer:
# Clear all media buffers
success = client.clear_media_buffers()
if success:
print("Media buffers cleared successfully")
Puffer entleert Rückruf
Behandlung von Pufferentleerungsereignissen:
def on_media_buffer_drained(stats):
"""Called when media buffers are drained"""
print("Media buffers drained")
if stats.audio:
print(f"Audio buffer: {stats.audio.duration.total_seconds()}s remaining")
if stats.video:
print(f"Video buffer: {stats.video.duration.total_seconds()}s remaining")
Verstehen von Pufferentleerungsereignissen:
Die on_media_buffer_drained_cb Callback wird aufgerufen, wenn die internen Audio- oder Videopuffer erschöpft sind. Dies geschieht, wenn Mediendaten mit einer Rate an die Sitzung übertragen werden, die die Rate übersteigt, mit der neue Mediendaten über add_audio() oder add_video() Anrufe.
Dieser Rückruf dient als Benachrichtigung, dass Sie Ihre Medienproduktionsrate erhöhen oder Ihre Veröffentlichungsstrategie anpassen sollten, um einen kontinuierlichen Medienfluss zu gewährleisten. Die Überwachung dieser Ereignisse hilft, Lücken oder Unterbrechungen in Ihrem veröffentlichten Stream zu vermeiden.
Rückruf-Hysterese-Verhalten:
Der Callback implementiert eine Hysterese, um eine übermäßige Auslösung zu verhindern. Nach dem anfänglichen Entleerungsereignis wird der Callback erst wieder aufgerufen, wenn der Puffer mit neuen Mediendaten aufgefüllt und anschließend wieder geleert wird. Dies verhindert eine Flut von wiederholten Benachrichtigungen, während der Puffer leer bleibt.
Verbindungsinformationen abrufen
Rufen Sie Ihre lokalen Verbindungsinformationen ab:
# Get the local connection
connection = client.get_connection()
if connection:
print(f"Connection ID: {connection.id}")
print(f"Connection data: {connection.data}")
print(f"Created at: {connection.creation_time}")
Ereignis-Rückrufe
Session-Rückrufe
Behandeln Sie Ereignisse auf Sitzungsebene:
def on_session_error(session, error_description, error_code):
"""Handle session errors"""
print(f"Session error: {error_description} (Code: {error_code})")
def on_session_connected(session):
"""Handle successful session connection"""
print(f"Connected to session: {session.id}")
def on_session_disconnected(session):
"""Handle session disconnection"""
print(f"Disconnected from session: {session.id}")
def on_ready_for_audio(session):
"""Called when the audio system is ready"""
print("Audio system ready - can now add audio")
Verbindungsrückrufe
Überwachen Sie die Verbindungen der Teilnehmer:
def on_connection_created(session, connection):
"""Handle new participant joining"""
print(f"Participant joined: {connection.id}")
print(f"Connection data: {connection.data}")
print(f"Created at: {connection.creation_time}")
def on_connection_dropped(session, connection):
"""Handle participant leaving"""
print(f"Participant left: {connection.id}")
Stream-Rückrufe
Behandlung von Stream-Ereignissen:
def on_stream_received(session, stream):
"""Handle new streams from other participants"""
print(f"Stream received: {stream.id} from connection {stream.connection.id}")
# Decide whether to subscribe based on your application logic
def on_stream_dropped(session, stream):
"""Handle streams being removed"""
print(f"Stream dropped: {stream.id}")
Verleger-Rückrufe
Handhabung von Veröffentlichungsereignissen:
def on_publisher_error(publisher, error_description, error_code):
"""Handle publisher errors"""
print(f"Publisher error: {error_description} (Code: {error_code})")
def on_stream_created(publisher):
"""Handle successful stream creation"""
print(f"Published stream created: {publisher.stream.id}")
def on_stream_destroyed(publisher):
"""Handle stream destruction"""
print(f"Published stream destroyed: {publisher.stream.id}")
Rückrufe von Abonnenten
Behandeln Sie Abonnement-Ereignisse:
def on_subscriber_error(subscriber, error_description, error_code):
"""Handle subscriber errors"""
print(f"Subscriber error: {error_description} (Code: {error_code})")
def on_subscriber_connected(subscriber):
"""Handle successful subscription"""
print(f"Subscribed to stream: {subscriber.stream.id}")
def on_subscriber_disconnected(subscriber):
"""Handle subscription disconnection"""
print(f"Unsubscribed from stream: {subscriber.stream.id}")
def on_render_frame(subscriber, video_frame):
"""Handle incoming video frames"""
width = video_frame.resolution.width
height = video_frame.resolution.height
print(f"Video frame: {width}x{height} in {video_frame.format} format")
Medienpuffer-Rückrufe
Behandlung von Medienpufferereignissen:
def on_media_buffer_drained(stats):
"""Handle media buffer drain events"""
print("Media buffers have been drained")
if stats.audio:
duration_s = stats.audio.duration.total_seconds()
print(f"Audio buffer: {duration_s}s")
if stats.video:
duration_s = stats.video.duration.total_seconds()
print(f"Video buffer: {duration_s}s")
Bereinigung von Ressourcen
Reinigen Sie die Ressourcen immer ordnungsgemäß:
try:
# Your application logic
success = client.connect(...)
# ... do work ...
except Exception as e:
print(f"Application error: {e}")
finally:
# Clean up resources
if client.is_publishing():
client.unpublish()
if client.is_connected():
client.disconnect()