جوزيف ناثان نشر 2 مايو 2021 أرسل تقرير نشر 2 مايو 2021 اتاحة امكانية بث حي من تطبيق Flutter اريد ان اعرف ما التقنيات التي توفر ذلك و ارخصهم ؟ شكرا مقدما . اقتباس
0 بلال زيادة نشر 2 مايو 2021 أرسل تقرير نشر 2 مايو 2021 توجد شركة agara يمكنك قراءة التوثيق الخاص بها من هنا , تقريباً هي أفضل شركة تقدم خدمات live Streaming. بعد الاشتراك في هذه الخدمة يمكنك تضمين مكتبة agora_rtc_engine داخل مشروعك يمكنك إيجاد المكتبة من هنا. في ملف pubspec.yaml تضع التالي agora_rtc_engine: ^3.3.3 ثم تقوم بتنفيذ الأمر التالي flutter pub get بعد الاشتراك ستجد APPI_ID, TOKEN حيث في ملف main.dart ستقوم بوضع كليهما بهذا الشكل const APP_ID = ''; const Token = ''; ثم تقوم بتعريف ملف main.dart بهذا الشكل import 'dart:async'; import 'package:agora_rtc_engine/rtc_engine.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Live Stream', theme: ThemeData( primarySwatch: Colors.blue, ), home: homePage(), ); } } ثم تقوم بتعريف homePage بهذا الشكل class homePage extends StatefulWidget { @override State<StatefulWidget> createState() => IndexState(); } class IndexState extends State<homePage> { final _channelController = TextEditingController(); bool _validateError = false; ClientRole _role = ClientRole.Broadcaster; @override void dispose() { // dispose input controller _channelController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Agora Flutter QuickStart'), ), body: Center( child: Container( padding: const EdgeInsets.symmetric(horizontal: 20), height: 400, child: Column( children: <Widget>[ Row( children: <Widget>[ Expanded( child: TextField( controller: _channelController, decoration: InputDecoration( errorText: _validateError ? 'Channel name is mandatory' : null, border: UnderlineInputBorder( borderSide: BorderSide(width: 1), ), hintText: 'Channel name', ), )) ], ), Column( children: [ ListTile( title: Text(ClientRole.Broadcaster.toString()), leading: Radio( value: ClientRole.Broadcaster, groupValue: _role, onChanged: (ClientRole value) { setState(() { _role = value; }); }, ), ), ListTile( title: Text(ClientRole.Audience.toString()), leading: Radio( value: ClientRole.Audience, groupValue: _role, onChanged: (ClientRole value) { setState(() { _role = value; }); }, ), ) ], ), Padding( padding: const EdgeInsets.symmetric(vertical: 20), child: Row( children: <Widget>[ Expanded( child: RaisedButton( onPressed: joinStream, child: Text('Join'), color: Colors.green, textColor: Colors.black, ), ) ], ), ) ], ), ), ), ); } /// زر الانضمام إلى البث Future<void> joinStream() async { setState(() { _channelController.text.isEmpty ? _validateError = true : _validateError = false; }); if (_channelController.text.isNotEmpty) { // انتظر إذن الكاميرا والميكروفون await _handleCameraAndMic(); // أدخل صفحة البث المباشر وانضم إلى القناة باستخدام اسم القناة والدور المحدد في صفحة تسجيل الدخول await Navigator.push( context, MaterialPageRoute( builder: (context) => CallPage( channelName: _channelController.text, role: _role, ), ), ); } } // لتفعيل الكاميرا و المايكرفون Future<void> _handleCameraAndMic() async { await PermissionHandler().requestPermissions( [PermissionGroup.camera, PermissionGroup.microphone], ); } } كود صفحة البث , يوجد شرح مضمن بداخله للدوال class livePage extends StatefulWidget { final String channelName; final ClientRole role; const livePage({Key key, this.channelName, this.role}) : super(key: key); @override _livePageState createState() => _livePageState(); } class _livePageState extends State<CallPage> { final _users = <int>[]; final _infoStrings = <String>[]; bool muted = false; RtcEngine _engine; @override void dispose() { _users.clear(); _engine.leaveChannel(); _engine.destroy(); super.dispose(); } @override void initState() { super.initState(); initialize(); } Future<void> initialize() async { if (APP_ID.isEmpty) { setState(() { _infoStrings.add( 'مفقود ، يرجى تقديم APP_ID الخاص بك في', ); _infoStrings.add('Agora Engine is not starting'); }); return; } await _initAgoraRtcEngine(); _addAgoraEventHandlers(); /// Join channel await _engine.joinChannel(Token, widget.channelName, null, 0); } // تخطيط شريط الأدوات Widget _toolbar() { if (widget.role == ClientRole.Audience) return Container(); return Container( alignment: Alignment.bottomCenter, padding: const EdgeInsets.symmetric(vertical: 48), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ RawMaterialButton( onPressed: _onToggleMute, child: Icon( muted ? Icons.mic_off : Icons.mic, color: muted ? Colors.white : Colors.blueAccent, size: 20.0, ), shape: CircleBorder(), elevation: 2.0, fillColor: muted ? Colors.blueAccent : Colors.white, padding: const EdgeInsets.all(12.0), ), RawMaterialButton( onPressed: () => _onCallEnd(context), child: Icon( Icons.call_end, color: Colors.white, size: 35.0, ), shape: CircleBorder(), elevation: 2.0, fillColor: Colors.redAccent, padding: const EdgeInsets.all(15.0), ), RawMaterialButton( onPressed: _onSwitchCamera, child: Icon( Icons.switch_camera, color: Colors.blueAccent, size: 20.0, ), shape: CircleBorder(), elevation: 2.0, fillColor: Colors.white, padding: const EdgeInsets.all(12.0), ) ], ), ); } Future<void> _initAgoraRtcEngine() async { RtcEngineConfig config = RtcEngineConfig(APP_ID); _engine = await RtcEngine.createWithConfig(config); await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); await _engine.setClientRole(widget.role); } void _addAgoraEventHandlers() { _engine.setEventHandler(RtcEngineEventHandler(error: (code) { setState(() { final info = 'onError: $code'; _infoStrings.add(info); }); }, joinChannelSuccess: (channel, uid, elapsed) { setState(() { final info = 'onJoinChannel: $channel, uid: $uid'; _infoStrings.add(info); }); }, leaveChannel: (stats) { setState(() { _infoStrings.add('onLeaveChannel'); _users.clear(); }); }, userJoined: (uid, elapsed) { setState(() { final info = 'userJoined: $uid'; _infoStrings.add(info); _users.add(uid); }); }, userOffline: (uid, elapsed) { setState(() { final info = 'userOffline: $uid'; _infoStrings.add(info); _users.remove(uid); }); })); } /// تخطيط شريط الأدوات Widget _toolbar() { if (widget.role == ClientRole.Audience) return Container(); return Container( alignment: Alignment.bottomCenter, padding: const EdgeInsets.symmetric(vertical: 48), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ RawMaterialButton( onPressed: _onToggleMute, child: Icon( muted ? Icons.mic_off : Icons.mic, color: muted ? Colors.white : Colors.blueAccent, size: 20.0, ), shape: CircleBorder(), elevation: 2.0, fillColor: muted ? Colors.blueAccent : Colors.white, padding: const EdgeInsets.all(12.0), ), RawMaterialButton( onPressed: () => _onCallEnd(context), child: Icon( Icons.call_end, color: Colors.white, size: 35.0, ), shape: CircleBorder(), elevation: 2.0, fillColor: Colors.redAccent, padding: const EdgeInsets.all(15.0), ), RawMaterialButton( onPressed: _onSwitchCamera, child: Icon( Icons.switch_camera, color: Colors.blueAccent, size: 20.0, ), shape: CircleBorder(), elevation: 2.0, fillColor: Colors.white, padding: const EdgeInsets.all(12.0), ) ], ), ); } // لوحة معلومات لعرض السجلات Widget _panel() { return Container( padding: const EdgeInsets.symmetric(vertical: 48), alignment: Alignment.bottomCenter, child: FractionallySizedBox( heightFactor: 0.5, child: Container( padding: const EdgeInsets.symmetric(vertical: 48), child: ListView.builder( reverse: true, itemCount: _infoStrings.length, itemBuilder: (BuildContext context, int index) { if (_infoStrings.isEmpty) { return null; } return Padding( padding: const EdgeInsets.symmetric( vertical: 3, horizontal: 10, ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Flexible( child: Container( padding: const EdgeInsets.symmetric( vertical: 2, horizontal: 5, ), decoration: BoxDecoration( color: Colors.yellowAccent, borderRadius: BorderRadius.circular(5), ), child: Text( _infoStrings[index], style: TextStyle(color: Colors.blueGrey), ), ), ) ], ), ); }, ), ), ), ); } // وقف البث المباشر void _onCallEnd(BuildContext context) { Navigator.pop(context); } /// صامت void _onToggleMute() { setState(() { muted = !muted; }); _engine.muteLocalAudioStream(muted); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Agora Flutter QuickStart'), ), backgroundColor: Colors.black, body: Center( child: Stack( children: <Widget>[ _panel(), _toolbar(), ], ), ), ); } } هذه الأكواد مجرد أمثلة يمكنك مراجعة توثيق agora من هنا فكل شيء مشروح بشكلٍ مفصل لكيفية تضمين المكتبة و الاشتراك في الخدمة. 1 اقتباس
السؤال
جوزيف ناثان
اتاحة امكانية بث حي من تطبيق Flutter
اريد ان اعرف ما التقنيات التي توفر ذلك و ارخصهم ؟
شكرا مقدما .
1 جواب على هذا السؤال
Recommended Posts
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.