本文分享了结合 WebRTC、开源 PHP Web 框架 Laravel 和 Socket.io 开发一个视频聊天应用的过程。
与其说是文章,不如说是代码的拆分讲解。但是对于开发者有一定的借鉴意义。
作者/开发者:Nyi Nyi Lwin
安装
1composer require php-junior/laravel-video-chat
由于 Laravel 5.5 新增了一个包自动发现功能(Package Auto-Discovery),所以省去了你手动添加 ServiceProvider。如果你不使用包自动发现功能,那么你需要在 config/app.php 中添加服务供应商。
1PhpJunior\LaravelVideoChat\LaravelVideoChatServiceProvider::class,
1php artisan vendor:publish --provider="PhpJunior\LaravelVideoChat\LaravelVideoChatServiceProvider"
1php artisan migrate
2php artisan storage:link
3
4change APP_URL in .env
下面这段是已发布的 config 文件的内容:
1return [
2 'relation' => [
3 'conversations' => PhpJunior\LaravelVideoChat\Models\Conversation\Conversation::class,
4 'group_conversations' => PhpJunior\LaravelVideoChat\Models\Group\Conversation\GroupConversation::class
5 ],
6 'user' => [
7 'model' => App\User::class,
8 'table' => 'users' // Existing user table name
9 ],
10 'table' => [
11 'conversations_table' => 'conversations',
12 'messages_table' => 'messages',
13 'group_conversations_table' => 'group_conversations',
14 'group_users_table' => 'group_users',
15 'files_table' => 'files'
16 ],
17 'channel' => [
18 'new_conversation_created' => 'new-conversation-created',
19 'chat_room' => 'chat-room',
20 'group_chat_room' => 'group-chat-room'
21 ],
22 'upload' => [
23 'storage' => 'public'
24 ]
25];
取消掉在config/app.php
配置文件中 App\Providers\BroadcastServiceProvider
的注释。
安装 JavaScript dependencies :
1npm install
2 npm install --save laravel-echo js-cookie vue-timeago socket.io socket.io-client webrtc-adapter vue-chat-scroll
如果你的 Web 应用与 Socket.IO 服务器运行在同一个域,你可通过head
中添加这段代码来访问客户端:
1<script src="//{{ Request::getHost() }}:6001/socket.io/socket.io.js"></script>
接下来,我们通过 socket.io
与 host` 来定义一个 Echo:
1require('webrtc-adapter');
2 window.Cookies = require('js-cookie');
3 import Echo from "laravel-echo"
4 window.io = require('socket.io-client');
5 window.Echo = new Echo({
6 broadcaster: 'socket.io',
7 host: window.location.hostname + ':6001'
8 });
最后,我们来用 Github 上的 tlaverdure/laravel-echo-server 来运行Socket.IO server。
在 resources/assets/js/app.js
文件中:
1import VueChatScroll from 'vue-chat-scroll';
2 import VueTimeago from 'vue-timeago';
3 Vue.use(VueChatScroll);
4 Vue.component('chat-room' , require('./components/laravel-video-chat/ChatRoom.vue'));
5 Vue.component('group-chat-room', require('./components/laravel-video-chat/GroupChatRoom.vue'));
6 Vue.component('video-section' , require('./components/laravel-video-chat/VideoSection.vue'));
7 Vue.component('file-preview' , require('./components/laravel-video-chat/FilePreview.vue'));
8 Vue.use(VueTimeago, {
9 name: 'timeago', // component name, `timeago` by default
10 locale: 'en-US',
11 locales: {
12 'en-US': require('vue-timeago/locales/en-US.json')
13 }
14 })
运行 npm run dev
。
功能
一对一视频通话
接收通话请求
群组聊天
文件分享
聊天功能
聊天,以及群组聊天
1$groups = Chat::getAllGroupConversations();
2$conversations = Chat::getAllConversations()
1<ul class="list-group">
2 @foreach($conversations as $conversation)
3 <li class="list-group-item">
4 @if($conversation->message->conversation->is_accepted)
5 <a href="#">
6 <h2>{{$conversation->user->name}}</h2>
7 @if(!is_null($conversation->message))
8 <span>{{ substr($conversation->message->text, 0, 20)}}</span>
9 @endif
10 </a>
11 @else
12 <a href="#">
13 <h2>{{$conversation->user->name}}</h2>
14 @if($conversation->message->conversation->second_user_id == auth()->user()->id)
15 <a href="accept_request_route" class="btn btn-xs btn-success">
16 Accept Message Request
17 </a>
18 @endif
19 </a>
20 @endif
21 </li>
22 @endforeach
23 @foreach($groups as $group)
24 <li class="list-group-item">
25 <a href="#">
26 <h2>{{$group->name}}</h2>
27 <span>{{ $group->users_count }} Member</span>
28 </a>
29 </li>
30 @endforeach
31</ul>
开启对话:
1Chat::startConversationWith($otherUserId);
接受对话:
1Chat::acceptMessageRequest($conversationId);
接收对话消息:
1$conversation = Chat::getConversationMessageById($conversationId);
1<chat-room :conversation="{{ $conversation }}" :current-user="{{ auth()->user() }}"></chat-room>
发送消息:
在该组件中你可以修改消息发送路径
1Chat::sendConversationMessage($conversationId, $message);
开始视频通话(非群组):
你可以修改视频通话频道。我在 'trigger/{id}定义视频通话频道,在
POST方法
$request->all()`字段。
1Chat::startVideoCall($conversationId , $request->all());
开始群组对话:
1Chat::createGroupConversation( $groupName , [ $otherUserId , $otherUserId2 ]);
获取群组对话消息:
1$conversation = Chat::getGroupConversationMessageById($groupConversationId);
1<group-chat-room :conversation="{{ $conversation }}" :current-user="{{ auth()->user() }}"></group-chat-room>
发送群组聊天消息:
1Chat::sendGroupConversationMessage($groupConversationId, $message);
添加成员进入群组:
1Chat::addMembersToExistingGroupConversation($groupConversationId, [ $otherUserId , $otherUserId2 ])
从群组中移除成员:
1Chat::removeMembersFromGroupConversation($groupConversationId, [ $otherUserId , $otherUserId2 ])
离开群组:
1Chat::leaveFromGroupConversation($groupConversationId);
文件共享
需要运行这段命令php artisan storage:link
发送文件至单一对话:
1Chat::sendFilesInConversation($conversationId , $request->file('files'));
发送文件至群组:
1Chat::sendFilesInGroupConversation($groupConversationId , $request->file('files'));