You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHP CodeIgniter+MySQL Web应用中集成Twilio视频通话及屏幕共享功能

嘿,我刚好有过把Twilio视频集成到CodeIgniter项目的实战经验,给你梳理一套完全贴合你需求的实现步骤,一步步来就行:

准备工作
  • 先搞定Twilio账户:注册后进入控制台,创建一个视频服务(Video Service),记下它的SID;同时获取你的Account SID和Auth Token(在账户设置里)。
  • 给CodeIgniter安装Twilio PHP SDK:用Composer在项目根目录执行composer require twilio/sdk,如果你的CI版本比较老,记得把vendor目录加入自动加载。
步骤1:配置CodeIgniter与Twilio

在application/config下新建twilio.php配置文件,把你的Twilio信息填进去:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

$config['twilio_account_sid'] = '你的Account SID';
$config['twilio_auth_token'] = '你的Auth Token';
$config['twilio_video_service_sid'] = '你的视频服务SID';
$config['twilio_api_key'] = '你的API Key'; // 需在Twilio控制台创建API密钥
$config['twilio_api_secret'] = '你的API Secret'; // 对应API密钥的Secret

然后在需要用到Twilio的控制器里加载这个配置:$this->load->config('twilio');

步骤2:实现管理员预约视频会议

首先得在MySQL里建一个会议表,用来存预约信息:

CREATE TABLE meetings (
    id INT AUTO_INCREMENT PRIMARY KEY,
    admin_id INT NOT NULL, -- 关联你的管理员表ID
    customer_id INT NULL, -- 可选,关联客户表ID(如果提前指定客户)
    room_name VARCHAR(50) UNIQUE NOT NULL, -- 这就是参会码,要唯一易输入
    scheduled_time DATETIME NOT NULL,
    status ENUM('scheduled', 'active', 'ended') DEFAULT 'scheduled',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

然后在后台控制器(比如application/controllers/Admin/Meetings.php)里写创建会议的方法:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Meetings extends CI_Controller {
    public function __construct() {
        parent::__construct();
        $this->load->model('Meeting_model');
        $this->load->config('twilio');
    }

    public function create() {
        // 生成8位随机参会码(字母+数字组合)
        $room_name = substr(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'), 0, 8);
        
        // 保存会议信息到数据库
        $data = [
            'admin_id' => $this->session->userdata('admin_id'),
            'customer_id' => $this->input->post('customer_id'),
            'room_name' => $room_name,
            'scheduled_time' => $this->input->post('scheduled_time')
        ];
        $this->Meeting_model->save($data);

        // 可选:给客户发邮件/站内信,告知参会码和会议时间
        redirect('admin/meetings');
    }
}

对应的Model(application/models/Meeting_model.php)里实现基础的插入、查询逻辑即可,这里就不赘述了。

步骤3:客户端用参会码加入会议

写客户端控制器(application/controllers/Customer/Meeting.php),处理参会码验证并生成Twilio访问令牌:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Meeting extends CI_Controller {
    public function __construct() {
        parent::__construct();
        $this->load->model('Meeting_model');
        $this->load->config('twilio');
    }

    public function join() {
        $room_name = trim($this->input->post('room_code'));
        // 验证参会码:存在且在会议开始后1小时内可加入
        $meeting = $this->Meeting_model->get_by_room_name($room_name);
        if (!$meeting || strtotime($meeting->scheduled_time) > time() + 3600) {
            $this->session->set_flashdata('error', '无效或过期的参会码');
            redirect('customer/meeting/join_form');
        }

        // 生成Twilio访问令牌
        $token = new Twilio\Jwt\AccessToken(
            $this->config->item('twilio_account_sid'),
            $this->config->item('twilio_api_key'),
            $this->config->item('twilio_api_secret'),
            3600, // 令牌有效期1小时
            'customer_' . $this->session->userdata('customer_id') // 唯一身份标识
        );

        // 添加视频权限,指定加入的房间
        $video_grant = new Twilio\Jwt\AccessToken\VideoGrant();
        $video_grant->setRoom($room_name);
        $token->addGrant($video_grant);

        // 把令牌和房间名传给前端视图
        $data['token'] = $token->toJWT();
        $data['room_name'] = $room_name;
        $this->load->view('customer/meeting_join', $data);
    }
}

管理员端的参会逻辑和这个类似,只需把身份标识换成admin_xxx即可。

步骤4:前端实现视频通话与屏幕共享

在application/views/customer/meeting_join.php里写前端交互逻辑:

<!DOCTYPE html>
<html>
<head>
    <title>加入视频会议</title>
    <script src="https://sdk.twilio.com/js/video/releases/2.28.0/twilio-video.min.js"></script>
    <style>
        #remote-videos { display: grid; grid-template-columns: repeat(auto-fill, 300px); gap: 10px; margin-top: 20px; }
        video { width: 100%; border-radius: 8px; }
    </style>
</head>
<body>
    <h3>会议房间:<?= $room_name ?></h3>
    <div id="local-video" style="width: 300px;"></div>
    <div id="remote-videos"></div>
    <button id="share-screen">开始屏幕共享</button>
    <button id="stop-share" disabled>停止屏幕共享</button>

    <script>
        const token = "<?= $token ?>";
        const roomName = "<?= $room_name ?>";
        let currentRoom;
        let screenTrack;

        // 连接到视频房间
        Twilio.Video.connect(token, {
            room: roomName,
            audio: true,
            video: { width: 1280 }
        }).then(room => {
            currentRoom = room;
            // 渲染本地视频
            const localVideo = document.createElement('video');
            room.localParticipant.tracks.forEach(track => {
                if (track.kind === 'video') {
                    localVideo.srcObject = track.mediaStream;
                    localVideo.autoplay = true;
                    localVideo.muted = true;
                    document.getElementById('local-video').appendChild(localVideo);
                }
            });

            // 监听远程参与者加入
            room.on('participantConnected', participant => {
                participant.tracks.forEach(publication => {
                    if (publication.isSubscribed) addRemoteVideo(publication.track);
                });
                participant.on('trackSubscribed', track => addRemoteVideo(track));
            });

            // 处理参与者离开
            room.on('participantDisconnected', participant => {
                document.querySelectorAll(`[data-identity="${participant.identity}"]`).forEach(el => el.remove());
            });
        }).catch(err => alert('连接失败:' + err.message));

        // 添加远程视频元素
        function addRemoteVideo(track) {
            const remoteVideo = document.createElement('video');
            remoteVideo.srcObject = track.mediaStream;
            remoteVideo.autoplay = true;
            remoteVideo.setAttribute('data-identity', track.participant.identity);
            document.getElementById('remote-videos').appendChild(remoteVideo);
        }

        // 屏幕共享逻辑
        document.getElementById('share-screen').addEventListener('click', async () => {
            try {
                screenTrack = await Twilio.Video.createScreenTrack({
                    video: { width: 1920 }
                });
                currentRoom.localParticipant.publishTrack(screenTrack);
                document.getElementById('share-screen').disabled = true;
                document.getElementById('stop-share').disabled = false;
            } catch (err) {
                alert('无法启动屏幕共享:' + err.message);
            }
        });

        document.getElementById('stop-share').addEventListener('click', () => {
            if (screenTrack) {
                screenTrack.stop();
                currentRoom.localParticipant.unpublishTrack(screenTrack);
                screenTrack = null;
                document.getElementById('share-screen').disabled = false;
                document.getElementById('stop-share').disabled = true;
            }
        });
    </script>
</body>
</html>
步骤5:多人会议优化

Twilio视频原生支持多人参会,只需在前端做两点优化:

  • 用CSS Grid/Flexbox布局远程视频,避免重叠和混乱(上面的代码已经加了基础布局)。
  • 维护参会者列表:监听participantConnected和participantDisconnected事件,动态更新页面上的参会者名单。
测试与部署注意事项
  • 必须用HTTPS:浏览器要求HTTPS才能访问摄像头、麦克风和屏幕共享,本地测试可以用ngrok把本地服务暴露成HTTPS地址。
  • 令牌有效期:别设置太长,1小时足够,避免令牌泄露后被滥用。
  • Twilio区域选择:创建视频服务时选择离你的用户最近的区域,降低通话延迟。
  • 错误处理:前端要补充权限拒绝、网络断开重连等场景的提示,提升用户体验。

内容的提问来源于stack exchange,提问作者Sujit Paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 06:33:15