@tencent-rtc/mcp 1.2.7 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/package.json +1 -1
  2. package/resource/doc/native_live/android/V2TXLiveCode_api_android.md +312 -0
  3. package/resource/doc/native_live/android/V2TXLiveDef_api_android.md +430 -0
  4. package/resource/doc/native_live/android/V2TXLivePlayerObserver_api_android.md +679 -0
  5. package/resource/doc/native_live/android/V2TXLivePlayer_api_android.md +671 -0
  6. package/resource/doc/native_live/android/V2TXLivePremier_api_android.md +271 -0
  7. package/resource/doc/native_live/android/V2TXLivePusherObserver_api_android.md +849 -0
  8. package/resource/doc/native_live/android/V2TXLivePusher_api_android.md +1046 -0
  9. package/resource/doc/native_live/flutter/V2TXLiveCode_api_flutter.md +460 -0
  10. package/resource/doc/native_live/flutter/V2TXLiveDef_api_flutter.md +558 -0
  11. package/resource/doc/native_live/flutter/V2TXLivePlayerObserver_api_flutter.md +865 -0
  12. package/resource/doc/native_live/flutter/V2TXLivePlayer_api_flutter.md +657 -0
  13. package/resource/doc/native_live/flutter/V2TXLivePremier_api_flutter.md +437 -0
  14. package/resource/doc/native_live/flutter/V2TXLivePusherObserver_api_flutter.md +335 -0
  15. package/resource/doc/native_live/flutter/V2TXLivePusher_api_flutter.md +748 -0
  16. package/resource/doc/native_live/iOS/V2TXLiveCode_api_iOS.md +327 -0
  17. package/resource/doc/native_live/iOS/V2TXLiveDef_api_iOS.md +507 -0
  18. package/resource/doc/native_live/iOS/V2TXLivePlayerObserver_api_iOS.md +507 -0
  19. package/resource/doc/native_live/iOS/V2TXLivePlayer_api_iOS.md +659 -0
  20. package/resource/doc/native_live/iOS/V2TXLivePremier_api_iOS.md +284 -0
  21. package/resource/doc/native_live/iOS/V2TXLivePusherObserver_api_iOS.md +814 -0
  22. package/resource/doc/native_live/iOS/V2TXLivePusher_api_iOS.md +1000 -0
  23. package/tools/common/get-faq.js +1 -1
  24. package/tools/common/get-faq.js.map +1 -1
  25. package/tools/definitions/get_native_live_api_def.js +23 -0
  26. package/tools/definitions/get_native_live_api_def.js.map +1 -0
  27. package/tools/index.js +4 -0
  28. package/tools/index.js.map +1 -1
  29. package/tools/native_live/get-native-live-api.js +31 -0
  30. package/tools/native_live/get-native-live-api.js.map +1 -0
  31. package/utils/report-cls-client.js +1 -1
  32. package/utils/report-es-client.js +1 -1
@@ -0,0 +1,865 @@
1
+ # Tencent Cloud Live Streaming SDK V2TXLivePlayerObserver Player Callback Interface Documentation
2
+
3
+ ## Feature Overview
4
+
5
+ `V2TXLivePlayerObserver` is the callback interface for the Tencent Cloud Live Streaming SDK. It provides notifications and event callbacks from the player, allowing you to monitor playback status, handle events, collect statistics, and more.
6
+
7
+ **File Path**: `v2_tx_live_player_observer.dart`
8
+ **Platform Support**: Flutter
9
+
10
+ **Core Features**:
11
+ - Monitor player status (errors, warnings, connection state)
12
+ - Receive audio/video playback event callbacks
13
+ - Access playback statistics and performance metrics
14
+ - Enable custom video rendering and audio processing
15
+ - Manage local recording tasks
16
+ - Receive and handle SEI messages
17
+
18
+ ## Callback Methods
19
+
20
+ ### Error and Warning Callbacks
21
+
22
+ #### onError - Playback Error Callback
23
+ ```dart
24
+ void onError(V2TXLivePlayer player, int code, String msg, Map<String, dynamic> extraInfo)
25
+ ```
26
+
27
+ **Description**: Invoked when the player encounters an error.
28
+
29
+ **Parameters**:
30
+ - `player`: The player instance that triggered the callback
31
+ - `code`: Error code (see `V2TXLiveCode`)
32
+ - `msg`: Error description
33
+ - `extraInfo`: Additional error details
34
+
35
+ **Typical Scenarios**:
36
+ - Invalid RTC stream pull parameters
37
+ - RTC stream pull timeout
38
+ - RTC stream pull server processing failure
39
+ - HEVC decoder not found
40
+
41
+ **Example**:
42
+ ```dart
43
+ player.addListener(V2TXLivePlayerObserver(
44
+ onError: (player, code, msg, extraInfo) {
45
+ switch (code) {
46
+ case V2TXLiveCode.V2TXLIVE_ERROR_INVALID_PARAMETER:
47
+ print('Invalid RTC stream pull parameters, $msg');
48
+ break;
49
+ case V2TXLiveCode.V2TXLIVE_ERROR_REQUEST_TIMEOUT:
50
+ print('RTC stream pull timeout, $msg');
51
+ break;
52
+ case V2TXLiveCode.V2TXLIVE_ERROR_SERVER_PROCESS_FAILED:
53
+ print('RTC stream pull server processing failed, please check the stream pull parameters, $msg');
54
+ break;
55
+ case V2TXLiveCode.V2TXLIVE_ERROR_DISCONNECTED:
56
+ print('Stream pull disconnected, $msg');
57
+ break;
58
+ case V2TXLiveCode.V2TXLIVE_ERROR_NO_AVAILABLE_HEVC_DECODERS:
59
+ print('HEVC decoder not found, you can switch to AVC stream for playback, $msg');
60
+ break;
61
+ default:
62
+ print('Other error, $msg');
63
+ break;
64
+ }
65
+ }
66
+ ));
67
+ ```
68
+
69
+ #### onWarning - Playback Warning Callback
70
+ ```dart
71
+ void onWarning(V2TXLivePlayer player, int code, String msg, Map<String, dynamic> extraInfo)
72
+ ```
73
+
74
+ **Description**: Invoked when the player encounters a warning.
75
+
76
+ **Parameters**:
77
+ - `player`: The player instance that triggered the callback
78
+ - `code`: Warning code (see `V2TXLiveCode`)
79
+ - `msg`: Warning description
80
+ - `extraInfo`: Additional warning details
81
+
82
+ **Typical Scenarios**:
83
+ - Video rendering stutter
84
+ - Decoder type change
85
+
86
+ **Example**:
87
+ ```dart
88
+ player.addListener(V2TXLivePlayerObserver(
89
+ onWarning: (player, code, msg, extraInfo) {
90
+ switch (code) {
91
+ case V2TXLiveCode.V2TXLIVE_WARNING_VIDEO_BLOCK:
92
+ print('Video rendering stutter detected');
93
+ break;
94
+ case V2TXLiveCode.V2TXLIVE_WARNING_CURRENT_DECODE_TYPE_CHANGED:
95
+ int codecType = extraInfo['codec_type'];
96
+ if (codecType == 0) {
97
+ print('Decoder type changed to h.264, $msg');
98
+ } else if (codecType == 1) {
99
+ print('Decoder type changed to h.265, $msg');
100
+ }
101
+ break;
102
+ default:
103
+ print('Other warning, $msg');
104
+ break;
105
+ }
106
+ }
107
+ ));
108
+ ```
109
+
110
+ ## Callback Type Enumeration
111
+
112
+ ### V2TXLivePlayerListenerType
113
+
114
+ Enumeration of all available player callback event types:
115
+
116
+ | Enum Value | Description | Parameter Details |
117
+ |--------|------|----------|
118
+ | `onError` | **Error Callback** – Unrecoverable SDK error | `code`: Error code<br>`msg`: Error message<br>`extraInfo`: Additional info |
119
+ | `onWarning` | **Warning Callback** – Non-critical issues (e.g., stutter, recoverable decoding failure) | `code`: Warning code<br>`msg`: Warning message<br>`extraInfo`: Additional info |
120
+ | `onVideoResolutionChanged` | **Video Resolution Change** | `width`: Video width<br>`height`: Video height |
121
+ | `onConnected` | **Connection Success** | `extraInfo`: Additional info |
122
+ | `onVideoPlaying` | **Video Playback Event** | `firstPlay`: First play flag<br>`extraInfo`: Additional info |
123
+ | `onAudioPlaying` | **Audio Playback Event** | `firstPlay`: First play flag<br>`extraInfo`: Additional info |
124
+ | `onVideoLoading` | **Video Loading Event** | `extraInfo`: Additional info |
125
+ | `onAudioLoading` | **Audio Loading Event** | `extraInfo`: Additional info |
126
+ | `onPlayoutVolumeUpdate` | **Playback Volume Update** | `volume`: Volume (0-100) |
127
+ | `onStatisticsUpdate` | **Playback Statistics** | `appCpu`: App CPU usage (%)<br>`systemCpu`: System CPU usage (%)<br>`width`: Video width<br>`height`: Video height<br>`fps`: Frame rate<br>`videoBitrate`: Video bitrate (Kbps)<br>`audioBitrate`: Audio bitrate (Kbps) |
128
+ | `onSnapshotComplete` | **Snapshot Complete** | `image`: Captured video frame (Uint8List) |
129
+ | `onRenderVideoFrame` | **Custom Video Rendering** | `videoFrame`: Video frame data (Map) |
130
+ | `onReceiveSeiMessage` | **SEI Message Reception** | `payloadType`: Message type<br>`data`: Message content (Uint8List) |
131
+ | `onPictureInPictureStateUpdate` | **Picture-in-Picture State Change** | `state`: State code<br>`message`: State message<br>`extraInfo`: Additional info |
132
+ | `onStreamSwitched` | **Stream Switch** | Parameters not detailed |
133
+
134
+ ## Callback Function Definition
135
+
136
+ ### V2TXLivePlayerObserver
137
+
138
+ Player observer callback function type:
139
+
140
+ ```dart
141
+ typedef V2TXLivePlayerObserver<P> = void Function(
142
+ V2TXLivePlayerListenerType type,
143
+ P? params
144
+ );
145
+ ```
146
+
147
+ **Parameters:**
148
+ - `type`: Callback event type (`V2TXLivePlayerListenerType`)
149
+ - `params`: Callback parameters (type P), varies by callback type
150
+
151
+ ## Callback Categories
152
+
153
+ ### Error and Warning Callbacks
154
+
155
+ #### onError
156
+ - **Importance**: High
157
+ - **Trigger**: When the SDK encounters an unrecoverable error
158
+ - **Recommendation**: Always listen for this callback and provide appropriate UI feedback based on the error code
159
+
160
+ #### onWarning
161
+ - **Importance**: Medium
162
+ - **Trigger**: When non-critical issues occur, such as stutter or recoverable decoding failures
163
+ - **Recommendation**: Optional to listen; useful for monitoring playback quality
164
+
165
+ ### Connection and Status Callbacks
166
+
167
+ #### onConnected - Connection Success Callback
168
+ ```dart
169
+ void onConnected(V2TXLivePlayer player, Map<String, dynamic> extraInfo)
170
+ ```
171
+
172
+ **Description**: Called when the player successfully connects to the server.
173
+
174
+ **Parameters**:
175
+ - `player`: The player instance
176
+ - `extraInfo`: Connection details
177
+
178
+ **Typical Scenarios**:
179
+ - Monitor network connection status
180
+ - Confirm player connection
181
+
182
+ **Example**:
183
+ ```dart
184
+ player.addListener(V2TXLivePlayerObserver(
185
+ onConnected: (player, extraInfo) {
186
+ print('Successfully connected to the server');
187
+ }
188
+ ));
189
+ ```
190
+
191
+ #### onVideoResolutionChanged - Video Resolution Change Callback
192
+ ```dart
193
+ void onVideoResolutionChanged(V2TXLivePlayer player, int width, int height)
194
+ ```
195
+
196
+ **Description**: Called when the video resolution changes.
197
+
198
+ **Parameters**:
199
+ - `player`: The player instance
200
+ - `width`: New video width
201
+ - `height`: New video height
202
+
203
+ **Typical Scenarios**:
204
+ - Adaptive video rendering
205
+ - Dynamic player layout adjustment
206
+
207
+ **Example**:
208
+ ```dart
209
+ player.addListener(V2TXLivePlayerObserver(
210
+ onVideoResolutionChanged: (player, width, height) {
211
+ print('Video stream resolution changed: width-$width, height-$height');
212
+ }
213
+ ));
214
+ ```
215
+
216
+ ### Playback Event Callbacks
217
+
218
+ #### onVideoPlaying - Video Playback Started
219
+ ```dart
220
+ void onVideoPlaying(V2TXLivePlayer player, bool firstPlay, Map<String, dynamic> extraInfo)
221
+ ```
222
+
223
+ **Description**: Called when video playback starts. For non-initial playback, this is paired with onVideoLoading.
224
+
225
+ **Parameters**:
226
+ - `player`: The player instance
227
+ - `firstPlay`: Whether this is the first playback
228
+ - `extraInfo`: Playback details
229
+
230
+ **Typical Scenarios**:
231
+ - Show playback status UI
232
+ - Start playback timer
233
+ - Log playback events
234
+ - Measure time to first frame
235
+
236
+ **Example**:
237
+ ```dart
238
+ player.addListener(V2TXLivePlayerObserver(
239
+ onVideoPlaying: (player, firstPlay, extraInfo) {
240
+ if (firstPlay) {
241
+ print('First playback started');
242
+ } else {
243
+ print('Playback started');
244
+ }
245
+ }
246
+ ));
247
+ ```
248
+
249
+ #### onVideoLoading - Video Loading Started
250
+ ```dart
251
+ void onVideoLoading(V2TXLivePlayer player, Map<String, dynamic> extraInfo)
252
+ ```
253
+
254
+ **Description**: Called when video data begins loading.
255
+
256
+ **Parameters**:
257
+ - `player`: The player instance
258
+ - `extraInfo`: Loading status
259
+
260
+ **Typical Scenarios**:
261
+ - Show loading animation
262
+ - Indicate buffering status
263
+
264
+ **Example**:
265
+ ```dart
266
+ player.addListener(V2TXLivePlayerObserver(
267
+ onVideoLoading: (player, extraInfo) {
268
+ print('Video playback loading started');
269
+ }
270
+ ));
271
+ ```
272
+
273
+ #### onAudioPlaying - Audio Playback Started
274
+ ```dart
275
+ void onAudioPlaying(V2TXLivePlayer player, bool firstPlay, Map<String, dynamic> extraInfo)
276
+ ```
277
+
278
+ **Description**: Called when audio playback starts.
279
+
280
+ **Parameters**:
281
+ - `player`: The player instance
282
+ - `firstPlay`: Whether this is the first playback
283
+ - `extraInfo`: Playback details
284
+
285
+ **Typical Scenarios**:
286
+ - Monitor audio playback status
287
+ - Pure audio stream playback
288
+
289
+ **Example**:
290
+ ```dart
291
+ player.addListener(V2TXLivePlayerObserver(
292
+ onAudioPlaying: (player, firstPlay, extraInfo) {
293
+ if (firstPlay) {
294
+ print('Audio playback started for the first time');
295
+ } else {
296
+ print('Audio playback started');
297
+ }
298
+ }
299
+ ));
300
+ ```
301
+
302
+ #### onAudioLoading - Audio Loading Started
303
+ ```dart
304
+ void onAudioLoading(V2TXLivePlayer player, Map<String, dynamic> extraInfo)
305
+ ```
306
+
307
+ **Description**: Called when audio data begins loading.
308
+
309
+ **Parameters**:
310
+ - `player`: The player instance
311
+ - `extraInfo`: Loading status
312
+
313
+ **Typical Scenarios**:
314
+ - Show loading animation
315
+ - Indicate buffering status
316
+
317
+ **Example**:
318
+ ```dart
319
+ player.addListener(V2TXLivePlayerObserver(
320
+ onAudioLoading: (player, extraInfo) {
321
+ print('Audio playback loading started');
322
+ }
323
+ ));
324
+ ```
325
+
326
+ ### Audio/Video Quality Monitoring Callback
327
+
328
+ #### onVideoResolutionChanged
329
+ - **Trigger**: When the live stream resolution changes
330
+
331
+ ### Audio/Video Data Processing Callbacks
332
+
333
+ #### onPlayoutVolumeUpdate - Playback Volume Callback
334
+ ```dart
335
+ void onPlayoutVolumeUpdate(V2TXLivePlayer player, int volume)
336
+ ```
337
+
338
+ **Description**: Real-time callback for playback volume.
339
+
340
+ **Parameters**:
341
+ - `player`: The player instance
342
+ - `volume`: Current playback volume (0-100)
343
+
344
+ **Prerequisite**: Call `enableVolumeEvaluation()` to enable volume evaluation.
345
+
346
+ **Typical Scenarios**:
347
+ - Display real-time volume
348
+ - Show audio waveform animation
349
+ - Detect mute status
350
+
351
+ **Example**:
352
+ ```dart
353
+ player.addListener(V2TXLivePlayerObserver(
354
+ onPlayoutVolumeUpdate: (player, volume) {
355
+ print('Audio playback volume: $volume');
356
+ }
357
+ ));
358
+ player.enableVolumeEvaluation(300);
359
+ ```
360
+
361
+ #### onRenderVideoFrame - Custom Video Rendering Callback
362
+ ```dart
363
+ void onRenderVideoFrame(V2TXLivePlayer player, Map<String, dynamic> videoFrame)
364
+ ```
365
+
366
+ **Description**: Callback for custom video frame rendering.
367
+
368
+ **Parameters**:
369
+ - `player`: The player instance
370
+ - `videoFrame`: Video frame data (pixel format, buffer type, etc.)
371
+
372
+ **Prerequisite**: Call `enableObserveVideoFrame()` to enable video frame callbacks.
373
+
374
+ **Typical Scenarios**:
375
+ - Custom video rendering
376
+ - Add filter effects
377
+ - Process video watermarks
378
+
379
+ **Example**:
380
+ ```dart
381
+ await player.enableObserveVideoFrame(true,
382
+ V2TXLivePixelFormat.v2TXLivePixelFormatTexture2D,
383
+ V2TXLiveBufferType.v2TXLiveBufferTypeTexture);
384
+
385
+ player.addListener(V2TXLivePlayerObserver(
386
+ onRenderVideoFrame: (player, videoFrame) {
387
+ print('Received video frame: ${videoFrame['width']}x${videoFrame['height']}');
388
+ }
389
+ ));
390
+ ```
391
+
392
+ #### onPlayoutAudioFrame - Audio Data Callback
393
+ ```dart
394
+ void onPlayoutAudioFrame(V2TXLivePlayer player, Map<String, dynamic> audioFrame)
395
+ ```
396
+
397
+ **Description**: Callback for audio frame data during playback.
398
+
399
+ **Parameters**:
400
+ - `player`: The player instance
401
+ - `audioFrame`: Audio frame data (sample rate, audio channels, etc.)
402
+
403
+ **Prerequisite**: Call `enableObserveAudioFrame()` to enable audio frame callbacks.
404
+
405
+ **Typical Scenarios**:
406
+ - Custom audio processing
407
+ - Audio analysis
408
+ - Real-time audio effects
409
+
410
+ **Example**:
411
+ ```dart
412
+ await player.enableObserveAudioFrame(true);
413
+
414
+ player.addListener(V2TXLivePlayerObserver(
415
+ onPlayoutAudioFrame: (player, audioFrame) {
416
+ print('Received audio frame, sample rate: ${audioFrame['sampleRate']}');
417
+ }
418
+ ));
419
+ ```
420
+
421
+ ### Statistics and Monitoring Callback
422
+
423
+ #### onStatisticsUpdate - Playback Statistics Callback
424
+ ```dart
425
+ void onStatisticsUpdate(V2TXLivePlayer player, Map<String, dynamic> statistics)
426
+ ```
427
+
428
+ **Description**: Real-time callback for playback statistics, triggered about every 2 seconds.
429
+
430
+ **Parameters**:
431
+ - `player`: The player instance
432
+ - `statistics`: Playback statistics:
433
+ - `appCpu`: App CPU usage (%)
434
+ - `systemCpu`: System CPU usage (%)
435
+ - `width`: Video width
436
+ - `height`: Video height
437
+ - `fps`: Frame rate
438
+ - `videoBitrate`: Video bitrate (Kbps)
439
+ - `audioBitrate`: Audio bitrate (Kbps)
440
+ - `audioSampleRate`: Audio sample rate
441
+ - `audioChannels`: Audio channel count
442
+
443
+ **Typical Scenarios**:
444
+ - Monitor playback quality
445
+ - Analyze performance
446
+ - Collect user experience metrics
447
+
448
+ **Example**:
449
+ ```dart
450
+ player.addListener(V2TXLivePlayerObserver(
451
+ onStatisticsUpdate: (player, statistics) {
452
+ print('Playback statistics:');
453
+ print(' - App CPU: ${statistics['appCpu']}%');
454
+ print(' - System CPU: ${statistics['systemCpu']}%');
455
+ print(' - Resolution: ${statistics['width']}x${statistics['height']}');
456
+ print(' - Frame rate: ${statistics['fps']}fps');
457
+ print(' - Video bitrate: ${statistics['videoBitrate']}Kbps');
458
+ print(' - Audio bitrate: ${statistics['audioBitrate']}Kbps');
459
+ }
460
+ ));
461
+ ```
462
+
463
+ ### Advanced Feature Callbacks
464
+
465
+ #### onSnapshotComplete - Snapshot Callback
466
+ ```dart
467
+ void onSnapshotComplete(V2TXLivePlayer player, Uint8List image)
468
+ ```
469
+
470
+ **Description**: Called when a snapshot operation completes.
471
+
472
+ **Parameters**:
473
+ - `player`: The player instance
474
+ - `image`: Captured video frame data (Uint8List)
475
+
476
+ **Typical Scenarios**:
477
+ - Save video snapshots
478
+ - Frame sharing
479
+
480
+ **Example**:
481
+ ```dart
482
+ player.addListener(V2TXLivePlayerObserver(
483
+ onSnapshotComplete: (player, image) {
484
+ print('Snapshot complete, image size: ${image.length} bytes');
485
+ // Save or share the image
486
+ }
487
+ ));
488
+ player.snapshot();
489
+ ```
490
+
491
+ #### onReceiveSeiMessage - SEI Message Callback
492
+ ```dart
493
+ void onReceiveSeiMessage(V2TXLivePlayer player, int payloadType, Uint8List data)
494
+ ```
495
+
496
+ **Description**: Called when an SEI (Supplemental Enhancement Information) message is received.
497
+
498
+ **Parameters**:
499
+ - `player`: The player instance
500
+ - `payloadType`: SEI message type
501
+ - `data`: SEI message data
502
+
503
+ **Prerequisite**: Call `enableReceiveSeiMessage()` to enable SEI message reception.
504
+
505
+ **Typical Scenarios**:
506
+ - Transmit scene information
507
+ - Send interactive messages
508
+ - Synchronize timestamps
509
+
510
+ **Example**:
511
+ ```dart
512
+ await player.enableReceiveSeiMessage(true, 5);
513
+
514
+ player.addListener(V2TXLivePlayerObserver(
515
+ onReceiveSeiMessage: (player, payloadType, data) {
516
+ print('Received SEI message, type: $payloadType, data size: ${data.length} bytes');
517
+ }
518
+ ));
519
+ ```
520
+
521
+ #### onStreamSwitched - Stream Switch Callback
522
+ ```dart
523
+ void onStreamSwitched(V2TXLivePlayer player, String url, int code)
524
+ ```
525
+
526
+ **Description**: Called after a stream resolution switch completes, triggered by `switchStream()`.
527
+
528
+ **Parameters**:
529
+ - `player`: The player instance
530
+ - `url`: Playback URL after switching
531
+ - `code`: Switch status code (0: success, -1: timeout, -2: server error, -3: client error)
532
+
533
+ **Typical Scenarios**:
534
+ - Monitor stream quality switching
535
+ - Provide switch status feedback
536
+
537
+ **Example**:
538
+ ```dart
539
+ player.startLivePlay("http://example.com/live/stream_1080p.flv");
540
+
541
+ player.addListener(V2TXLivePlayerObserver(
542
+ onStreamSwitched: (player, url, code) {
543
+ if (code == 0) {
544
+ print('Switch successful');
545
+ } else if (code == -1) {
546
+ print('Switch timeout');
547
+ } else if (code == -2) {
548
+ print('Switch failed, server error');
549
+ } else if (code == -3) {
550
+ print('Switch failed, client error');
551
+ }
552
+ }
553
+ ));
554
+
555
+ await player.switchStream("http://example.com/live/stream_720p.flv");
556
+ ```
557
+
558
+ ### Local Recording Callbacks
559
+
560
+ #### onLocalRecordBegin - Recording Start Callback
561
+ ```dart
562
+ void onLocalRecordBegin(V2TXLivePlayer player, int code, String storagePath)
563
+ ```
564
+
565
+ **Description**: Called when a local recording task starts (triggered by `startLocalRecording()`).
566
+
567
+ **Parameters**:
568
+ - `player`: The player instance
569
+ - `code`: Recording status code
570
+ - `storagePath`: Recording file path
571
+
572
+ **Status Codes**:
573
+ - `0`: Recording started successfully
574
+ - `-1`: Internal error
575
+ - `-2`: Invalid file extension
576
+ - `-6`: Recording already started
577
+ - `-7`: Recording file already exists
578
+ - `-8`: No write permission for recording directory
579
+
580
+ #### onLocalRecording - Recording Progress Callback
581
+ ```dart
582
+ void onLocalRecording(V2TXLivePlayer player, int durationMs, String storagePath)
583
+ ```
584
+
585
+ **Description**: Called to report ongoing recording progress. Frequency matches the `interval` parameter in `startLocalRecording()`.
586
+
587
+ **Parameters**:
588
+ - `player`: The player instance
589
+ - `durationMs`: Recorded duration (milliseconds)
590
+ - `storagePath`: Recording file path
591
+
592
+ **Typical Scenarios**:
593
+ - Display recording progress
594
+ - Enforce recording duration limits
595
+ - Monitor recording status
596
+
597
+ #### onLocalRecordComplete - Recording Complete Callback
598
+ ```dart
599
+ void onLocalRecordComplete(V2TXLivePlayer player, int code, String storagePath)
600
+ ```
601
+
602
+ **Description**: Called when a recording task completes (triggered by `stopLocalRecording()`).
603
+
604
+ **Parameters**:
605
+ - `player`: The player instance
606
+ - `code`: Recording completion status code
607
+ - `storagePath`: Recording file path
608
+
609
+ **Status Codes**:
610
+ - `0`: Recording ended successfully
611
+ - `-1`: Recording failed
612
+ - `-2`: Ended due to resolution or orientation change
613
+ - `-3`: Duration too short or no data collected
614
+
615
+ **Example**:
616
+ ```dart
617
+ player.addListener(V2TXLivePlayerObserver(
618
+ onLocalRecordBegin: (player, code, storagePath) {
619
+ print('Recording started');
620
+ },
621
+ onLocalRecording: (player, durationMs, storagePath) {
622
+ print('Recording in progress..., durationMs: $durationMs');
623
+ },
624
+ onLocalRecordComplete: (player, code, storagePath) {
625
+ print('Recording completed');
626
+ }
627
+ ));
628
+
629
+ V2TXLiveLocalRecordingParams params = V2TXLiveLocalRecordingParams(
630
+ filePath: "filepath",
631
+ interval: 2000
632
+ );
633
+ V2TXLiveCode code = await player.startLocalRecording(params);
634
+ if (code == V2TXLiveCode.V2TXLIVE_OK) {
635
+ print('Recording started successfully');
636
+ } else if (code == V2TXLiveCode.V2TXLIVE_ERROR_INVALID_PARAMETER) {
637
+ print('Invalid recording parameters');
638
+ } else if (code == V2TXLiveCode.V2TXLIVE_ERROR_REFUSED) {
639
+ print('Recording call refused');
640
+ }
641
+ ```
642
+
643
+ ### Usage Examples
644
+
645
+ #### Basic Player Callback Implementation
646
+ ```dart
647
+ class MyPlayerObserver extends V2TXLivePlayerObserver {
648
+ @override
649
+ void onError(V2TXLivePlayer player, int code, String msg, Map<String, dynamic> extraInfo) {
650
+ // Handle playback error
651
+ print('PlayerError: Error code: $code, Error message: $msg');
652
+ }
653
+
654
+ @override
655
+ void onConnected(V2TXLivePlayer player, Map<String, dynamic> extraInfo) {
656
+ // Handle successful connection
657
+ print('Player: Successfully connected to server');
658
+ }
659
+
660
+ @override
661
+ void onVideoPlaying(V2TXLivePlayer player, bool firstPlay, Map<String, dynamic> extraInfo) {
662
+ // Video playback started
663
+ if (firstPlay) {
664
+ print('Player: First playback started');
665
+ }
666
+ }
667
+
668
+ @override
669
+ void onStatisticsUpdate(V2TXLivePlayer player, Map<String, dynamic> statistics) {
670
+ // Update playback statistics
671
+ print('PlayerStats: FPS: ${statistics['fps']}, Bitrate: ${statistics['videoBitrate']}');
672
+ }
673
+ }
674
+
675
+ // Set callback observer
676
+ V2TXLivePlayer player = await V2TXLivePlayer.create();
677
+ player.addListener(MyPlayerObserver());
678
+ ```
679
+
680
+ #### Custom Video Processing Example
681
+ ```dart
682
+ class VideoProcessorObserver extends V2TXLivePlayerObserver {
683
+ @override
684
+ void onRenderVideoFrame(V2TXLivePlayer player, Map<String, dynamic> videoFrame) {
685
+ // Custom video frame processing
686
+ // Add filters, watermarks, etc.
687
+ processVideoFrame(videoFrame);
688
+ }
689
+
690
+ void processVideoFrame(Map<String, dynamic> frame) {
691
+ print('Processing video frame: ${frame['width']}x${frame['height']}');
692
+ }
693
+ }
694
+
695
+ // Enable custom video frame callback
696
+ await player.enableObserveVideoFrame(true);
697
+ player.addListener(VideoProcessorObserver());
698
+ ```
699
+
700
+ #### Local Recording Monitoring Example
701
+ ```dart
702
+ class RecordingObserver extends V2TXLivePlayerObserver {
703
+ @override
704
+ void onLocalRecordBegin(V2TXLivePlayer player, int code, String storagePath) {
705
+ if (code == 0) {
706
+ print('Recording: Started, file path: $storagePath');
707
+ } else {
708
+ print('Recording: Failed, error code: $code');
709
+ }
710
+ }
711
+
712
+ @override
713
+ void onLocalRecording(V2TXLivePlayer player, int durationMs, String storagePath) {
714
+ updateRecordingProgress(durationMs);
715
+ }
716
+
717
+ @override
718
+ void onLocalRecordComplete(V2TXLivePlayer player, int code, String storagePath) {
719
+ if (code == 0) {
720
+ print('Recording: Completed, file path: $storagePath');
721
+ } else {
722
+ print('Recording: Abnormally ended, status code: $code');
723
+ }
724
+ }
725
+
726
+ void updateRecordingProgress(int durationMs) {
727
+ print('Recording progress: ${durationMs}ms');
728
+ }
729
+ }
730
+
731
+ player.addListener(RecordingObserver());
732
+ ```
733
+
734
+ ## Notes
735
+
736
+ ### Callback Thread Safety
737
+ - **Main Thread Execution**: All callbacks except custom rendering run on the UI main thread.
738
+ - **Thread Switching**: Custom rendering callbacks may run on non-UI threads; ensure thread safety.
739
+
740
+ ### Performance Impact
741
+ - **Custom Rendering**: Enabling custom video rendering can impact playback performance. Use only when necessary.
742
+ - **Audio Processing**: Audio data callbacks may increase CPU usage. Control processing frequency.
743
+ - **Statistics Frequency**: Statistics callbacks are triggered about every 2 seconds. Avoid heavy operations in these callbacks.
744
+
745
+ ### Memory Management
746
+ - **Release Observers**: Remove unused observer objects promptly to prevent memory leaks.
747
+ - **Callback References**: Avoid strong references to the player in callbacks to prevent reference cycles.
748
+ - **Resource Cleanup**: Remove all observers before destroying the player.
749
+
750
+ ### Error Handling
751
+ - **Error Code Handling**: Parse error codes and provide user-friendly feedback.
752
+ - **Exception Handling**: Add try/catch in callbacks to prevent crashes.
753
+ - **State Recovery**: Implement recovery logic based on error types.
754
+
755
+ ### Permissions and Configuration
756
+ - **Storage Permission**: Local recording requires storage permission and enough free space.
757
+ - **Network Permission**: The player needs network permission for stream pulling.
758
+ - **Audio Permission**: Audio playback requires audio permission.
759
+
760
+ ### Best Practices
761
+
762
+ #### Error Handling Best Practice
763
+ ```dart
764
+ player.addListener(V2TXLivePlayerObserver(
765
+ onError: (player, code, msg, extraInfo) {
766
+ try {
767
+ // Show user-friendly error messages
768
+ switch (code) {
769
+ case V2TXLiveCode.V2TXLIVE_ERROR_INVALID_PARAMETER:
770
+ showToast('Invalid playback URL, please check and try again');
771
+ break;
772
+ case V2TXLiveCode.V2TXLIVE_ERROR_REQUEST_TIMEOUT:
773
+ showToast('Network connection timeout, please check your network and try again');
774
+ break;
775
+ default:
776
+ showToast('Playback failed, please try again later');
777
+ break;
778
+ }
779
+ } catch (e) {
780
+ print('Error handling exception: $e');
781
+ }
782
+ }
783
+ ));
784
+ ```
785
+
786
+ #### Performance Monitoring Best Practice
787
+ ```dart
788
+ player.addListener(V2TXLivePlayerObserver(
789
+ onStatisticsUpdate: (player, statistics) {
790
+ double fps = statistics['fps'];
791
+ double bitrate = statistics['videoBitrate'];
792
+
793
+ if (fps < 15) {
794
+ print('Warning: Low frame rate ($fps fps)');
795
+ }
796
+
797
+ if (bitrate < 500) {
798
+ print('Warning: Low video bitrate ($bitrate Kbps)');
799
+ }
800
+ }
801
+ ));
802
+ ```
803
+
804
+ #### Memory Management Best Practice
805
+ ```dart
806
+ class PlayerManager {
807
+ V2TXLivePlayer? player;
808
+ V2TXLivePlayerObserver? observer;
809
+
810
+ Future<void> initPlayer() async {
811
+ player = await V2TXLivePlayer.create();
812
+ observer = V2TXLivePlayerObserver(
813
+ onConnected: (player, extraInfo) {
814
+ print('Connection successful');
815
+ }
816
+ );
817
+ player!.addListener(observer!);
818
+ }
819
+
820
+ void dispose() {
821
+ // Remove observer first
822
+ if (player != null && observer != null) {
823
+ player!.removeListener(observer!);
824
+ }
825
+ // Then destroy player
826
+ player?.destroy();
827
+ player = null;
828
+ observer = null;
829
+ }
830
+ }
831
+ ```
832
+
833
+ ## FAQs
834
+
835
+ ### Q: Why am I not receiving callbacks?
836
+ A: Check the following:
837
+ 1. Is the observer correctly set using `player.addListener(observer)`?
838
+ 2. Has the player been created and initialized successfully?
839
+ 3. Are callbacks registered at the correct time?
840
+
841
+ ### Q: What should I do if custom rendering callbacks have poor performance?
842
+ A: Recommendations:
843
+ 1. Optimize rendering logic and avoid heavy computations.
844
+ 2. Use asynchronous processing to minimize main thread blocking.
845
+ 3. Enable custom rendering only when necessary.
846
+
847
+ ### Q: How do I resolve local recording failures?
848
+ A: Check:
849
+ 1. Is storage permission granted?
850
+ 2. Is the storage path valid and writable?
851
+ 3. Is there enough free storage space?
852
+
853
+ ### Q: Why am I not receiving SEI messages?
854
+ A: Confirm:
855
+ 1. Has `enableReceiveSeiMessage()` been called?
856
+ 2. Does payloadType match the sender?
857
+ 3. Does the stream contain SEI messages?
858
+
859
+ ## File Information
860
+
861
+ - **File Path**: `/Users/borryzhang/Work/Project/liteav_flutter/sdk/trtc/v3/lib/v2_tx_live_player_observer.dart`
862
+ - **File Size**: 3.26 KB
863
+ - **Total Lines**: 140
864
+ - **Platform Support**: Flutter
865
+ - **SDK Version**: v3