Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to display other user's camera a little bit faster? #1227

Closed
ChurikiTenna opened this issue Jul 24, 2023 · 7 comments
Closed
Labels
waiting for customer response waiting for customer response, or closed by no-reponse bot

Comments

@ChurikiTenna
Copy link

Is your feature request related to a problem? Please describe.
When a user turns the camera on, it takes few seconds for the camera to show up on the other devices.

Describe the solution you'd like
Is it possible to make it faster? (less than 1 sec is desirable) Or, is there any way to do so on my side?

@littleGnAl
Copy link
Collaborator

Can you describe what APIs you use for your case?

@littleGnAl littleGnAl added the waiting for customer response waiting for customer response, or closed by no-reponse bot label Jul 24, 2023
@ChurikiTenna
Copy link
Author

ChurikiTenna commented Aug 1, 2023

I use video call api.

agora_rtc_engine: ^6.2.0

This is the related code.


import 'dart:async';
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fortunetelling_commons/fortunetelling_commons.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:cloud_functions/cloud_functions.dart';

class AgoraHelper {
  AgoraHelper({required this.didUpdate});

  final Function() didUpdate;

  int? remoteUid;
  bool localUserJoined = false;
  bool remoteVideoIsOn = true;
  late RtcEngine engine;
  var channelName = '';
  Timer? timer;

  RtcEngineEventHandler eventHandler() {
    return RtcEngineEventHandler(
        onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
      debugPrint("local user ${connection.localUid} joined");
      localUserJoined = true;
      didUpdate();
    }, onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {
      debugPrint("remote user $remoteUid joined");
      this.remoteUid = remoteUid;
      didUpdate();
    }, onUserOffline: (RtcConnection connection, int remoteUid,
            UserOfflineReasonType reason) {
      debugPrint("remote user $remoteUid left channel");
      this.remoteUid = null;
      didUpdate();
    }, onTokenPrivilegeWillExpire: (RtcConnection connection, String token) {
      debugPrint(
          '[onTokenPrivilegeWillExpire] connection: ${connection.toJson()}, token: $token');
    }, onRemoteVideoStateChanged: (connection, uid, state, reason, inelaspedt) {
      debugPrint("onRemoteVideoStateChanged $remoteUid $uid $state");
      if (uid == remoteUid) {
        debugPrint("onRemoteVideoStateChanged!!");
        remoteVideoIsOn = [
          RemoteVideoState.remoteVideoStateStarting,
          RemoteVideoState.remoteVideoStateDecoding
        ].contains(state);
        didUpdate();
      }
    });
  }

  Future<void> initAgora(String tellerId, String userId, int myUID) async {
    channelName = tellerId + userId; //widget.teller.uid+widget.user.uid;
    try {
      // retrieve permissions
      await [Permission.microphone].request();
      var result = await FirebaseFunctions.instance
          .httpsCallable('agoraToken')
          .call({"channelId": channelName, "uid": myUID});
      debugPrint("result.data ${result.data}");
      var token = result.data;

      //create the engine
      engine = createAgoraRtcEngine();
      await engine.initialize(const RtcEngineContext(
        appId: '<my app id>',
        channelProfile: ChannelProfileType.channelProfileLiveBroadcasting,
      ));

      engine.registerEventHandler(eventHandler());

      await engine.setClientRole(role: ClientRoleType.clientRoleBroadcaster);
      enableVideo(false);
      await engine.joinChannel(
        token: token,
        channelId: channelName,
        uid: myUID,
        options: const ChannelMediaOptions(),
      );
    } catch (e) {
      rethrow;
    }
  }

  enableVideo(bool enable) async {
    debugPrint("enableVideo $enable");
    if (enable) {
      await [Permission.camera].request();
      await engine.enableLocalVideo(true);
      await engine.enableVideo();
      await engine.startPreview();
    } else {
      await engine.enableLocalVideo(false);
      await engine.disableVideo();
      await engine.stopPreview();
    }
  }

  startTimer(AgoraCallHistoryData history, Function(int) updateSec) {
    timer?.cancel();
    timer = Timer.periodic(
      const Duration(seconds: 1),
      (timer) {
        if (history.startTime == null) return;
        var seconds =
            DateTime.now().difference(history.startTime!.toDate()).inSeconds;
        updateSec(seconds);
      },
    );
  }

  Stream<AgoraCallHistoryData?> startStream(AgoraCallHistoryData callHistory) {
    return AgoraCallHistoryData.collection
        .doc(callHistory.uid)
        .snapshots()
        .map((event) {
      //debugPrint("startStream ${event.data()}");
      if (!event.exists) return null;
      callHistory =
          AgoraCallHistoryData.fromMap(event.data() as Map<String, dynamic>);
      return callHistory;
    });
  }

  leave(AgoraCallHistoryData callHistory) async {
    callHistory.endTime = Timestamp.now();
    callHistory.status = CallStatus.finished;
    AgoraCallHistoryData.save(callHistory);
    await engine.leaveChannel();
    engine.unregisterEventHandler(eventHandler());
    timer?.cancel();
  }

  Widget localVideoView(AgoraHelper helper, bool videoEnabled) {
    return Container(
        height: double.infinity,
        alignment: Alignment.bottomLeft,
        child: SafeArea(
            child: Container(
          margin: const EdgeInsets.all(12),
          decoration: Decorations.round(rad: 100, color: Colors.black12),
          clipBehavior: Clip.hardEdge,
          width: 100,
          height: 100,
          child: helper.localUserJoined
              ? (videoEnabled
                  ? AgoraVideoView(
                      controller: VideoViewController(
                        rtcEngine: helper.engine,
                        canvas: const VideoCanvas(uid: 0),
                      ),
                    )
                  : const Icon(CupertinoIcons.video_camera,
                      color: Colors.white))
              : const Padding(
                  padding: EdgeInsets.all(20),
                  child: CircularProgressIndicator(
                    strokeWidth: 8,
                    color: Colors.black26,
                  ),
                ),
        )));
  }

  Widget remoteVideo(String placeholder, String imagePath) {
    if (remoteUid != null) {
      return Container(
          color: AppColors.palePink,
          width: double.infinity,
          height: double.infinity,
          alignment: Alignment.center,
          child: remoteVideoIsOn
              ? AgoraVideoView(
                  controller: VideoViewController.remote(
                  rtcEngine: engine,
                  canvas: VideoCanvas(uid: remoteUid),
                  connection: RtcConnection(channelId: channelName),
                ))
              : placeholderW());
    } else {
      return Container(
          color: AppColors.palePink,
          width: double.infinity,
          height: double.infinity,
          alignment: Alignment.center,
          child: Texts.bold(placeholder, 14));
    }
  }

  Widget placeholderW() {
    return Container(
        padding: EdgeInsets.all(20),
        color: const Color.fromARGB(255, 238, 235, 235),
        alignment: Alignment.center,
        child: Icon(CupertinoIcons.phone, color: Colors.black38, size: 48));
  }
}

@github-actions github-actions bot removed the waiting for customer response waiting for customer response, or closed by no-reponse bot label Aug 1, 2023
@littleGnAl
Copy link
Collaborator

Based on your code, I think you should change the state of remoteVideoIsOn inside the onUserJoined rather than onRemoteVideoStateChanged, maybe you can log the time of the onUserJoined and onRemoteVideoStateChanged to see how long these callbacks are received.

@littleGnAl littleGnAl added wontfix This will not be worked on waiting for customer response waiting for customer response, or closed by no-reponse bot labels Aug 1, 2023
@ChurikiTenna
Copy link
Author

All users initially join the call without cameras.
So, I have to use onRemoteVideoStateChanged.
Is there any other workarounds?

@github-actions github-actions bot removed the waiting for customer response waiting for customer response, or closed by no-reponse bot label Aug 2, 2023
@littleGnAl
Copy link
Collaborator

Can you log out the elapsed in onUserJoined /onRemoteVideoStateChanged ? I'm not very sure if the callback takes too long to receive.

@littleGnAl littleGnAl added waiting for customer response waiting for customer response, or closed by no-reponse bot and removed wontfix This will not be worked on labels Aug 3, 2023
@github-actions
Copy link
Contributor

Without additional information, we are unfortunately not sure how to resolve this issue. We are therefore reluctantly going to close this bug for now. If you find this problem please file a new issue with the same description, what happens, logs and the output. All system setups can be slightly different so it's always better to open new issues and reference the related ones. Thanks for your contribution.

@github-actions
Copy link
Contributor

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please raise a new issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 31, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
waiting for customer response waiting for customer response, or closed by no-reponse bot
Projects
None yet
Development

No branches or pull requests

2 participants