1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15+ import 'package:flutter/foundation.dart' ;
1516import 'package:flutter/material.dart' ;
1617
1718import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
@@ -52,10 +53,19 @@ class VideoTrackRenderer extends StatefulWidget {
5253
5354class _VideoTrackRendererState extends State <VideoTrackRenderer > {
5455 rtc.RTCVideoRenderer ? _renderer;
56+ // for flutter web only.
57+ bool _rendererReadyForWeb = false ;
5558 EventsListener <TrackEvent >? _listener;
5659 // Used to compute visibility information
5760 late GlobalKey _internalKey;
5861
62+ Future <rtc.RTCVideoRenderer > _initializeRenderer () async {
63+ _renderer ?? = rtc.RTCVideoRenderer ();
64+ await _renderer! .initialize ();
65+ await _attach ();
66+ return _renderer! ;
67+ }
68+
5969 void disposeRenderer () {
6070 try {
6171 _renderer? .srcObject = null ;
@@ -70,12 +80,12 @@ class _VideoTrackRendererState extends State<VideoTrackRenderer> {
7080 void initState () {
7181 super .initState ();
7282 _internalKey = widget.track.addViewKey ();
73- () async {
74- _renderer ?? = rtc. RTCVideoRenderer ();
75- await _renderer ! . initialize ();
76- await _attach ( );
77- setState (() {} );
78- }();
83+ if (kIsWeb) {
84+ () async {
85+ await _initializeRenderer ();
86+ setState (() => _rendererReadyForWeb = true );
87+ }( );
88+ }
7989 }
8090
8191 @override
@@ -118,9 +128,9 @@ class _VideoTrackRendererState extends State<VideoTrackRenderer> {
118128 }
119129 }
120130
121- @override
122- Widget build ( BuildContext context) => _renderer != null
123- ? Builder (
131+ Widget _videoViewForWeb () => ! _rendererReadyForWeb
132+ ? Container ()
133+ : Builder (
124134 key: _internalKey,
125135 builder: (ctx) {
126136 // let it render before notifying build
@@ -135,8 +145,37 @@ class _VideoTrackRendererState extends State<VideoTrackRenderer> {
135145 objectFit: widget.fit,
136146 );
137147 },
138- )
139- : Container ();
148+ );
149+
150+ Widget _videoViewForNative () => FutureBuilder (
151+ future: _initializeRenderer (),
152+ builder: (context, snapshot) {
153+ if (snapshot.hasData && _renderer != null ) {
154+ return Builder (
155+ key: _internalKey,
156+ builder: (ctx) {
157+ // let it render before notifying build
158+ WidgetsBindingCompatible .instance
159+ ? .addPostFrameCallback ((timeStamp) {
160+ widget.track.onVideoViewBuild? .call (_internalKey);
161+ });
162+ return rtc.RTCVideoView (
163+ _renderer! ,
164+ mirror: _shouldMirror (),
165+ filterQuality: FilterQuality .medium,
166+ objectFit: widget.fit,
167+ );
168+ },
169+ );
170+ }
171+ return Container ();
172+ });
173+
174+ // FutureBuilder will cause flickering for flutter web. so using
175+ // different rendering methods for web and native.
176+ @override
177+ Widget build (BuildContext context) =>
178+ kIsWeb ? _videoViewForWeb () : _videoViewForNative ();
140179
141180 bool _shouldMirror () {
142181 // off for screen share
0 commit comments