利用Laravel、Socket.IO和WebRTC实现视频聊天应用

本文分享了结合 WebRTC、开源 PHP Web 框架 Laravel 和 Socket.io 开发一个视频聊天应用的过程。

与其说是文章,不如说是代码的拆分讲解。但是对于开发者有一定的借鉴意义。

作者/开发者:Nyi Nyi Lwin

请移步 Github 查看完整 Demo

安装

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'));

填写常用邮箱,接收社区更新

WebRTC 中文社区由

运营