mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-25 12:09:09 +08:00
初步完成直播websocket讨论
This commit is contained in:
parent
2dee6efb04
commit
b374309c1f
@ -24,4 +24,12 @@ class IndexController extends Controller
|
|||||||
$this->view->setVar('vip_courses', $indexService->getVipCourses());
|
$this->view->setVar('vip_courses', $indexService->getVipCourses());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Get("/im", name="web.im")
|
||||||
|
*/
|
||||||
|
public function imAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,47 +2,81 @@
|
|||||||
|
|
||||||
namespace App\Http\Web\Controllers;
|
namespace App\Http\Web\Controllers;
|
||||||
|
|
||||||
class LiveController extends Controller
|
use App\Http\Web\Services\Live as LiveService;
|
||||||
|
use App\Traits\Response as ResponseTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @RoutePrefix("/live")
|
||||||
|
*/
|
||||||
|
class LiveController extends \Phalcon\Mvc\Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
|
use ResponseTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Get("/stats", name="web.live.stats")
|
* @Get("/{id:[0-9]+}/members", name="web.live.members")
|
||||||
*/
|
*/
|
||||||
public function statsAction()
|
public function membersAction($id)
|
||||||
|
{
|
||||||
|
$list = [
|
||||||
|
[
|
||||||
|
'username' => '直飞机',
|
||||||
|
'avatar' => 'http://tp1.sinaimg.cn/5619439268/180/40030060651/1',
|
||||||
|
'status' => 'online',
|
||||||
|
'sign' => '高舍炮打的准',
|
||||||
|
'id' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'username' => '直飞机2',
|
||||||
|
'avatar' => 'http://tp1.sinaimg.cn/5619439268/180/40030060651/1',
|
||||||
|
'status' => 'online',
|
||||||
|
'sign' => '高舍炮打的准',
|
||||||
|
'id' => 2,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'username' => '直飞机3',
|
||||||
|
'avatar' => 'http://tp1.sinaimg.cn/5619439268/180/40030060651/1',
|
||||||
|
'status' => 'online',
|
||||||
|
'sign' => '高舍炮打的准',
|
||||||
|
'id' => 3,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$content = ['data' => ['list' => $list]];
|
||||||
|
|
||||||
|
return $this->jsonSuccess($content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Post("/{id:[0-9]+}/bind", name="web.live.bind")
|
||||||
|
*/
|
||||||
|
public function bindAction($id)
|
||||||
|
{
|
||||||
|
$service = new LiveService();
|
||||||
|
|
||||||
|
$service->bindUser($id);
|
||||||
|
|
||||||
|
return $this->jsonSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Post("/{id:[0-9]+}/unbind", name="web.live.unbind")
|
||||||
|
*/
|
||||||
|
public function unbindAction($id)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Get("/users", name="web.live.users")
|
* @Post("/{id:[0-9]+}/message", name="web.live.message")
|
||||||
*/
|
*/
|
||||||
public function usersAction()
|
public function messageAction($id)
|
||||||
{
|
{
|
||||||
|
$service = new LiveService();
|
||||||
|
|
||||||
}
|
$service->sendMessage($id);
|
||||||
|
|
||||||
/**
|
|
||||||
* @Post("/login", name="web.live.login")
|
|
||||||
*/
|
|
||||||
public function loginAction()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Post("/logout", name="web.live.logout")
|
|
||||||
*/
|
|
||||||
public function logoutAction()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Post("/message", name="web.live.message")
|
|
||||||
*/
|
|
||||||
public function messageAction()
|
|
||||||
{
|
|
||||||
|
|
||||||
|
return $this->jsonSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
27
app/Http/Web/Controllers/MessengerController.php
Normal file
27
app/Http/Web/Controllers/MessengerController.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Web\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Web\Services\Index as IndexService;
|
||||||
|
|
||||||
|
class MessengerController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Get("/", name="web.index")
|
||||||
|
*/
|
||||||
|
public function indexAction()
|
||||||
|
{
|
||||||
|
$this->siteSeo->setKeywords($this->siteSettings['keywords']);
|
||||||
|
$this->siteSeo->setDescription($this->siteSettings['description']);
|
||||||
|
|
||||||
|
$indexService = new IndexService();
|
||||||
|
|
||||||
|
$this->view->setVar('slides', $indexService->getSlides());
|
||||||
|
$this->view->setVar('lives', $indexService->getLives());
|
||||||
|
$this->view->setVar('new_courses', $indexService->getNewCourses());
|
||||||
|
$this->view->setVar('free_courses', $indexService->getFreeCourses());
|
||||||
|
$this->view->setVar('vip_courses', $indexService->getVipCourses());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -53,13 +53,13 @@ class PublicController extends \Phalcon\Mvc\Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Post("/learning", name="web.learning")
|
* @Post("/{id:[0-9]+}/learning", name="web.learning")
|
||||||
*/
|
*/
|
||||||
public function learningAction()
|
public function learningAction($id)
|
||||||
{
|
{
|
||||||
$service = new LearningService();
|
$service = new LearningService();
|
||||||
|
|
||||||
$service->handle();
|
$service->handle($id);
|
||||||
|
|
||||||
return $this->jsonSuccess();
|
return $this->jsonSuccess();
|
||||||
}
|
}
|
||||||
|
67
app/Http/Web/Services/Live.php
Normal file
67
app/Http/Web/Services/Live.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Web\Services;
|
||||||
|
|
||||||
|
use App\Services\Frontend\ChapterTrait;
|
||||||
|
use GatewayClient\Gateway;
|
||||||
|
|
||||||
|
class Live extends Service
|
||||||
|
{
|
||||||
|
|
||||||
|
use ChapterTrait;
|
||||||
|
|
||||||
|
public function bindUser($id)
|
||||||
|
{
|
||||||
|
$chapter = $this->checkChapterCache($id);
|
||||||
|
|
||||||
|
$user = $this->getCurrentUser();
|
||||||
|
|
||||||
|
$userId = $user->id > 0 ?: $this->session->getId();
|
||||||
|
|
||||||
|
$clientId = $this->request->getPost('client_id');
|
||||||
|
|
||||||
|
$groupName = $this->getGroupName($chapter->id);
|
||||||
|
|
||||||
|
Gateway::$registerAddress = '127.0.0.1:1238';
|
||||||
|
|
||||||
|
Gateway::bindUid($clientId, $userId);
|
||||||
|
|
||||||
|
Gateway::joinGroup($clientId, $groupName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendMessage($id)
|
||||||
|
{
|
||||||
|
$chapter = $this->checkChapterCache($id);
|
||||||
|
|
||||||
|
$from = $this->request->getPost('from');
|
||||||
|
$to = $this->request->getPost('to');
|
||||||
|
|
||||||
|
$content = [
|
||||||
|
'username' => $from['username'],
|
||||||
|
'avatar' => $from['avatar'],
|
||||||
|
'content' => $from['content'],
|
||||||
|
'fromid' => $from['id'],
|
||||||
|
'id' => $to['id'],
|
||||||
|
'type' => $to['type'],
|
||||||
|
'timestamp' => 1000 * time(),
|
||||||
|
'mine' => false,
|
||||||
|
];
|
||||||
|
|
||||||
|
$message = json_encode([
|
||||||
|
'type' => 'show_message',
|
||||||
|
'content' => $content,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$groupName = $this->getGroupName($chapter->id);
|
||||||
|
|
||||||
|
Gateway::$registerAddress = '127.0.0.1:1238';
|
||||||
|
|
||||||
|
Gateway::sendToGroup($groupName, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getGroupName($groupId)
|
||||||
|
{
|
||||||
|
return "chapter_{$groupId}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,32 +2,28 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{% set course_url = url({'for':'web.course.show','id':chapter.course.id}) %}
|
<div class="layui-breadcrumb breadcrumb">
|
||||||
|
<a href="/">首页</a>
|
||||||
<div class="breadcrumb">
|
<a href="{{ url({'for':'web.course.list'}) }}">全部课程</a>
|
||||||
<span class="layui-breadcrumb">
|
<a href="{{ url({'for':'web.course.show','id':chapter.course.id}) }}">{{ chapter.course.title }}</a>
|
||||||
<span><i class="layui-icon layui-icon-return"></i> <a href="{{ course_url }}">返回课程主页</a></span>
|
<a><cite>{{ chapter.title }}</cite></a>
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="layout-main clearfix">
|
<div class="live-player container">
|
||||||
<div class="layout-content">
|
<div id="player"></div>
|
||||||
<div id="player" class="container"></div>
|
|
||||||
</div>
|
|
||||||
<div class="layout-sidebar">
|
|
||||||
<div class="sidebar-online container">
|
|
||||||
<div class="layui-tab layui-tab-brief">
|
|
||||||
<ul class="layui-tab-title">
|
|
||||||
<li class="layui-this">讨论</li>
|
|
||||||
<li>成员</li>
|
|
||||||
</ul>
|
|
||||||
<div class="layui-tab-content">
|
|
||||||
<div class="layui-tab-item layui-show" id="tab-comments" data-url="#"></div>
|
|
||||||
<div class="layui-tab-item" id="tab-users" data-url="#"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="layui-hide">
|
||||||
|
<input type="hidden" name="user.id" value="{{ auth_user.id }}">
|
||||||
|
<input type="hidden" name="user.name" value="{{ auth_user.name }}">
|
||||||
|
<input type="hidden" name="user.avatar" value="{{ auth_user.avatar }}">
|
||||||
|
<input type="hidden" name="chapter.id" value="{{ chapter.id }}">
|
||||||
|
<input type="hidden" name="chapter.plan_id" value="{{ chapter.me.plan_id }}">
|
||||||
|
<input type="hidden" name="chapter.play_urls" value='{{ chapter.play_urls|json_encode }}'>
|
||||||
|
<input type="hidden" name="chapter.learning_url" value="{{ url({'for':'web.learning','id':chapter.id}) }}">
|
||||||
|
<input type="hidden" name="im.members_url" value="{{ url({'for':'web.live.members','id':chapter.id}) }}">
|
||||||
|
<input type="hidden" name="im.bind_user_url" value="{{ url({'for':'web.live.bind','id':chapter.id}) }}">
|
||||||
|
<input type="hidden" name="im.send_msg_url" value="{{ url({'for':'web.live.message','id':chapter.id}) }}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -36,119 +32,12 @@
|
|||||||
|
|
||||||
<script src="//imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.2.js"></script>
|
<script src="//imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.2.js"></script>
|
||||||
|
|
||||||
|
{{ js_include('lib/layui/layui.js') }}
|
||||||
|
{{ js_include('web/js/live.player.js') }}
|
||||||
|
{{ js_include('web/js/live.im.js') }}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block inline_js %}
|
{% block inline_js %}
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
var interval = null;
|
|
||||||
var intervalTime = 5000;
|
|
||||||
var position = 0;
|
|
||||||
var chapterId = '{{ chapter.id }}';
|
|
||||||
var courseId = '{{ chapter.course.id }}';
|
|
||||||
var planId = '{{ chapter.me.plan_id }}';
|
|
||||||
var userId = '{{ auth_user.id }}';
|
|
||||||
var requestId = getRequestId();
|
|
||||||
var playUrls = JSON.parse('{{ chapter.play_urls|json_encode }}');
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
live: true,
|
|
||||||
autoplay: true,
|
|
||||||
h5_flv: true,
|
|
||||||
width: 760,
|
|
||||||
height: 450
|
|
||||||
};
|
|
||||||
|
|
||||||
if (playUrls.rtmp && playUrls.rtmp.od) {
|
|
||||||
options.rtmp = playUrls.rtmp.od;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playUrls.rtmp && playUrls.rtmp.hd) {
|
|
||||||
options.rtmp_hd = playUrls.rtmp.hd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playUrls.rtmp && playUrls.rtmp.sd) {
|
|
||||||
options.rtmp_sd = playUrls.rtmp.sd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playUrls.flv && playUrls.flv.od) {
|
|
||||||
options.flv = playUrls.flv.od;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playUrls.flv && playUrls.flv.hd) {
|
|
||||||
options.flv_hd = playUrls.flv.hd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playUrls.flv && playUrls.flv.sd) {
|
|
||||||
options.flv_sd = playUrls.flv.sd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playUrls.m3u8 && playUrls.m3u8.od) {
|
|
||||||
options.m3u8 = playUrls.m3u8.od;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playUrls.m3u8 && playUrls.m3u8.hd) {
|
|
||||||
options.m3u8_hd = playUrls.m3u8.hd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playUrls.m3u8 && playUrls.m3u8.sd) {
|
|
||||||
options.m3u8_sd = playUrls.m3u8.sd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userId !== '0' && planId !== '0') {
|
|
||||||
options.listener = function (msg) {
|
|
||||||
if (msg.type === 'play') {
|
|
||||||
start();
|
|
||||||
} else if (msg.type === 'pause') {
|
|
||||||
stop();
|
|
||||||
} else if (msg.type === 'end') {
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var player = new TcPlayer('player', options);
|
|
||||||
|
|
||||||
if (position > 0) {
|
|
||||||
player.currentTime(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
function start() {
|
|
||||||
if (interval != null) {
|
|
||||||
clearInterval(interval);
|
|
||||||
interval = null;
|
|
||||||
}
|
|
||||||
interval = setInterval(learning, intervalTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
function stop() {
|
|
||||||
clearInterval(interval);
|
|
||||||
interval = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function learning() {
|
|
||||||
$.ajax({
|
|
||||||
type: 'POST',
|
|
||||||
url: '/learning',
|
|
||||||
data: {
|
|
||||||
request_id: requestId,
|
|
||||||
chapter_id: chapterId,
|
|
||||||
course_id: courseId,
|
|
||||||
user_id: userId,
|
|
||||||
plan_id: planId,
|
|
||||||
interval: intervalTime,
|
|
||||||
position: player.currentTime(),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRequestId() {
|
|
||||||
var id = Date.now().toString(36);
|
|
||||||
id += Math.random().toString(36).substr(3);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
99
app/Http/Web/Views/index/im.volt
Normal file
99
app/Http/Web/Views/index/im.volt
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
{% extends 'templates/full.volt' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block inline_js %}
|
||||||
|
|
||||||
|
{{ js_include('lib/layui/layui.js') }}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
layui.use(['jquery', 'layim'], function () {
|
||||||
|
|
||||||
|
var bindUserUrl = '/live/42425/bind';
|
||||||
|
var sendMessageUrl = '/live/42425/message';
|
||||||
|
|
||||||
|
var socket = new WebSocket('ws://127.0.0.1:8282');
|
||||||
|
var $ = layui.jquery;
|
||||||
|
var layim = layui.layim;
|
||||||
|
|
||||||
|
layim.config({
|
||||||
|
brief: true,
|
||||||
|
init: {
|
||||||
|
mine: {
|
||||||
|
'username': '直飞机',
|
||||||
|
'avatar': 'http://tp1.sinaimg.cn/5619439268/180/40030060651/1',
|
||||||
|
'status': 'online',
|
||||||
|
'sign': '高舍炮打的准',
|
||||||
|
'id': 1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
members: {
|
||||||
|
url: '/live/members',
|
||||||
|
data: {
|
||||||
|
chapter_id: 123
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).chat({
|
||||||
|
name: '直播讨论',
|
||||||
|
type: 'group',
|
||||||
|
avatar: 'http://tp1.sinaimg.cn/5619439268/180/40030060651/1',
|
||||||
|
id: 123,
|
||||||
|
});
|
||||||
|
|
||||||
|
layim.on('sendMessage', function (res) {
|
||||||
|
sendMessage(res.mine, res.to);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.onopen = function () {
|
||||||
|
console.log('socket connect success');
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.onclose = function () {
|
||||||
|
console.log('socket connect close');
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.onerror = function () {
|
||||||
|
console.log('socket connect error');
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.onmessage = function (e) {
|
||||||
|
var data = JSON.parse(e.data);
|
||||||
|
console.log(data);
|
||||||
|
if (data.type === 'ping') {
|
||||||
|
socket.send('pong...');
|
||||||
|
} else if (data.type === 'bind_user') {
|
||||||
|
bindUser(data.client_id);
|
||||||
|
} else if (data.type === 'show_message') {
|
||||||
|
showMessage(data.content);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function bindUser(clientId) {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: bindUserUrl,
|
||||||
|
data: {client_id: clientId}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendMessage(from, to) {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
dataType: 'json',
|
||||||
|
url: sendMessageUrl,
|
||||||
|
data: {from: from, to: to}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMessage(message) {
|
||||||
|
layim.getMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -1,338 +0,0 @@
|
|||||||
|
|
||||||
<div id="video" style="width: 600px; height: 400px;">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{ js_include('library/chplayer/chplayer.min.js') }}
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
var videoObject = {
|
|
||||||
container: '#video', //容器的ID
|
|
||||||
variable: 'player',
|
|
||||||
autoplay: true, //是否自动播放
|
|
||||||
loaded: 'loadedHandler', //当播放器加载后执行的函数
|
|
||||||
video: 'http://vod-cdn.koogua.com/20171012_fixed.m3u8'
|
|
||||||
//video: 'http://www.flashls.org/playlists/test_001/stream_1000k_48k_640x360.m3u8'
|
|
||||||
};
|
|
||||||
|
|
||||||
var player = new chplayer(videoObject);
|
|
||||||
|
|
||||||
function loadedHandler() {
|
|
||||||
changeText('.playerstate', '状态:播放器已加载,建立监听:监听元数据,监听其它状态');
|
|
||||||
player.addListener('error', errorHandler); //监听视频加载出错
|
|
||||||
player.addListener('loadedmetadata', loadedMetaDataHandler); //监听元数据
|
|
||||||
player.addListener('play', playHandler); //监听暂停播放
|
|
||||||
player.addListener('pause', pauseHandler); //监听暂停播放
|
|
||||||
player.addListener('timeupdate', timeUpdateHandler); //监听播放时间
|
|
||||||
player.addListener('seeking', seekingHandler); //监听跳转播放
|
|
||||||
player.addListener('seeked', seekedHandler); //监听跳转播放完成
|
|
||||||
player.addListener('volumechange', volumeChangeHandler); //监听音量改变
|
|
||||||
player.addListener('full', fullHandler); //监听全屏/非全屏切换
|
|
||||||
player.addListener('ended', endedHandler); //监听全屏/非全屏切换
|
|
||||||
player.addListener('videochange', videoChangeHandler); //监听视频地址改变
|
|
||||||
}
|
|
||||||
|
|
||||||
function errorHandler() {
|
|
||||||
changeText('.playerstate', '状态:视频加载错误,停止执行其它动作,等待其它操作');
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadedMetaDataHandler() {
|
|
||||||
var metaData = player.getMetaDate();
|
|
||||||
var html = '';
|
|
||||||
if(parseInt(metaData['videoWidth']) > 0) {
|
|
||||||
changeText('.playerstate', '状态:获取到元数据信息,如果数据错误,可以使用延迟获取');
|
|
||||||
html += '总时间:' + metaData['duration'] + '秒,';
|
|
||||||
html += '音量:' + metaData['volume'] + '(范围0-1),';
|
|
||||||
html += '播放器的宽度:' + metaData['width'] + 'px,';
|
|
||||||
html += '播放器的高度:' + metaData['height'] + 'px,';
|
|
||||||
html += '视频的实际宽度:' + metaData['videoWidth'] + 'px,';
|
|
||||||
html += '视频的实际高度:' + metaData['videoHeight'] + 'px,';
|
|
||||||
html += '是否暂停状态:' + metaData['paused'];
|
|
||||||
} else {
|
|
||||||
changeText('.playerstate', '状态:未正确获取到元数据信息');
|
|
||||||
html = '您正在使用移动端或iPad观看本页面,该平台限制了视频加载,只有在点击了播放器后才能加载视频及获取元数据信息';
|
|
||||||
}
|
|
||||||
changeText('.metadata', html);
|
|
||||||
}
|
|
||||||
|
|
||||||
function playHandler() {
|
|
||||||
//player.animateResume();//继续播放所有弹幕
|
|
||||||
changeText('.playstate', '播放状态:播放');
|
|
||||||
window.setTimeout(function() {
|
|
||||||
loadedMetaDataHandler();
|
|
||||||
}, 1000);
|
|
||||||
loadedMetaDataHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
function pauseHandler() {
|
|
||||||
//player.animatePause();//暂停所有弹幕
|
|
||||||
changeText('.playstate', '播放状态:暂停');
|
|
||||||
loadedMetaDataHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
function timeUpdateHandler() {
|
|
||||||
changeText('.currenttimestate', '当前播放时间(秒):' + player.time);
|
|
||||||
}
|
|
||||||
|
|
||||||
function seekingHandler() {
|
|
||||||
changeText('.seekstate', '跳转动作:正在进行跳转');
|
|
||||||
}
|
|
||||||
|
|
||||||
function seekedHandler() {
|
|
||||||
changeText('.seekstate', '跳转动作:跳转完成');
|
|
||||||
}
|
|
||||||
|
|
||||||
function volumeChangeHandler() {
|
|
||||||
changeText('.volumechangestate', '当前音量:' + player.volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
function fullHandler() {
|
|
||||||
var html = player.getByElement('.fullstate').innerHTML;
|
|
||||||
if(player.full) {
|
|
||||||
html += ',全屏';
|
|
||||||
} else {
|
|
||||||
html += ',否';
|
|
||||||
}
|
|
||||||
changeText('.fullstate', html);
|
|
||||||
}
|
|
||||||
|
|
||||||
function endedHandler() {
|
|
||||||
changeText('.endedstate', '播放结束');
|
|
||||||
}
|
|
||||||
var videoChangeNum = 0;
|
|
||||||
|
|
||||||
function videoChangeHandler() {
|
|
||||||
videoChangeNum++;
|
|
||||||
changeText('.videochangestate', '视频地址改变了' + videoChangeNum + '次');
|
|
||||||
}
|
|
||||||
|
|
||||||
function seekTime() {
|
|
||||||
var time = parseInt(player.getByElement('.seektime').value);
|
|
||||||
var metaData = player.getMetaDate();
|
|
||||||
var duration = metaData['duration'];
|
|
||||||
if(time < 0) {
|
|
||||||
alert('请填写大于0的数字');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(time > duration) {
|
|
||||||
alert('请填写小于' + duration + '的数字');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
player.seek(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeVolume() {
|
|
||||||
var volume = player.getByElement('.changevolume').value;
|
|
||||||
volume = Math.floor(volume * 100) / 100;
|
|
||||||
if(volume < 0) {
|
|
||||||
alert('请填写大于0的数字');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(volume > 1) {
|
|
||||||
alert('请填写小于1的数字');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
player.changeVolume(volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeSize() {
|
|
||||||
player.changeSize(w, h)
|
|
||||||
}
|
|
||||||
|
|
||||||
function frontFun() {
|
|
||||||
alert('点击了前一集');
|
|
||||||
}
|
|
||||||
|
|
||||||
function nextFun() {
|
|
||||||
alert('点击了下一集');
|
|
||||||
}
|
|
||||||
|
|
||||||
function newVideo() {
|
|
||||||
var videoUrl = player.getByElement('.videourl').value;
|
|
||||||
changeVideo(videoUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
function newVideo2() {
|
|
||||||
var videoUrl = player.getByElement('.videourl2').value;
|
|
||||||
changeVideo(videoUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeVideo(videoUrl) {
|
|
||||||
if(player == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newVideoObject = {
|
|
||||||
container: '#video', //容器的ID
|
|
||||||
variable: 'player',
|
|
||||||
autoplay: true, //是否自动播放
|
|
||||||
loaded: 'loadedHandler', //当播放器加载后执行的函数
|
|
||||||
video: videoUrl
|
|
||||||
};
|
|
||||||
//判断是需要重新加载播放器还是直接换新地址
|
|
||||||
|
|
||||||
if(player.playerType == 'html5video') {
|
|
||||||
if(player.getFileExt(videoUrl) == '.flv' || player.getFileExt(videoUrl) == '.m3u8' || player.getFileExt(videoUrl) == '.f4v' || videoUrl.substr(0, 4) == 'rtmp') {
|
|
||||||
player.removeChild();
|
|
||||||
|
|
||||||
player = null;
|
|
||||||
player = new chplayer();
|
|
||||||
player.embed(newVideoObject);
|
|
||||||
} else {
|
|
||||||
player.newVideo(newVideoObject);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(player.getFileExt(videoUrl) == '.mp4' || player.getFileExt(videoUrl) == '.webm' || player.getFileExt(videoUrl) == '.ogg') {
|
|
||||||
player = null;
|
|
||||||
player = new chplayer();
|
|
||||||
player.embed(newVideoObject);
|
|
||||||
} else {
|
|
||||||
player.newVideo(newVideoObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function newElement() {
|
|
||||||
var attribute = {
|
|
||||||
list: [{
|
|
||||||
type: 'image',
|
|
||||||
url: 'screenshot/logo.png',
|
|
||||||
radius: 30, //圆角弧度
|
|
||||||
width: 30, //定义宽,必需要定义
|
|
||||||
height: 30, //定义高,必需要定义
|
|
||||||
alpha: 0.9, //透明度
|
|
||||||
marginLeft: 10,
|
|
||||||
marginRight: 10,
|
|
||||||
marginTop: 10,
|
|
||||||
marginBottom: 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'text', //说明是文本
|
|
||||||
text: '这里是一个普通的元件,不支持HTML', //文本内容
|
|
||||||
fontColor: '#FFFFFF',
|
|
||||||
fontSize: 14,
|
|
||||||
fontFamily: '"Microsoft YaHei", YaHei, "微软雅黑", SimHei,"\5FAE\8F6F\96C5\9ED1", "黑体",Arial',
|
|
||||||
lineHeight: 30,
|
|
||||||
alpha: 1, //透明度
|
|
||||||
//paddingLeft:10,//左边距离
|
|
||||||
paddingRight: 10, //右边距离
|
|
||||||
paddingTop: 0,
|
|
||||||
paddingBottom: 0,
|
|
||||||
marginLeft: 0,
|
|
||||||
marginRight: 0,
|
|
||||||
marginTop: 10,
|
|
||||||
marginBottom: 0,
|
|
||||||
//backgroundColor:'#000000',
|
|
||||||
backAlpha: 0.5,
|
|
||||||
backRadius: 30 //背景圆角弧度
|
|
||||||
}
|
|
||||||
],
|
|
||||||
x: 10, //x轴坐标
|
|
||||||
y: 10, //y轴坐标
|
|
||||||
//position:[1,1],//位置[x轴对齐方式(0=左,1=中,2=右),y轴对齐方式(0=上,1=中,2=下),x轴偏移量(不填写或null则自动判断,第一个值为0=紧贴左边,1=中间对齐,2=贴合右边),y轴偏移量(不填写或null则自动判断,0=紧贴上方,1=中间对齐,2=紧贴下方)]
|
|
||||||
alpha: 1,
|
|
||||||
backgroundColor: '#000000',
|
|
||||||
backAlpha: 0.5,
|
|
||||||
backRadius: 60 //背景圆角弧度
|
|
||||||
};
|
|
||||||
var el = player.addElement(attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
function newDanmu() {
|
|
||||||
//弹幕说明
|
|
||||||
|
|
||||||
var danmuObj = {
|
|
||||||
list: [{
|
|
||||||
type: 'image',
|
|
||||||
url: 'screenshot/logo.png',
|
|
||||||
radius: 30, //圆角弧度
|
|
||||||
width: 30, //定义宽,必需要定义
|
|
||||||
height: 30, //定义高,必需要定义
|
|
||||||
alpha: 0.9, //透明度
|
|
||||||
marginLeft: 10,
|
|
||||||
marginRight: 10,
|
|
||||||
marginTop: 0,
|
|
||||||
marginBottom: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'text', //说明是文本
|
|
||||||
text: '演示弹幕内容,弹幕只支持普通文本,不支持HTML', //文本内容
|
|
||||||
fontColor: '#FFFFFF',
|
|
||||||
fontSize: 14,
|
|
||||||
fontFamily: '"Microsoft YaHei", YaHei, "微软雅黑", SimHei,"\5FAE\8F6F\96C5\9ED1", "黑体",Arial',
|
|
||||||
lineHeight: 30,
|
|
||||||
alpha: 1, //透明度
|
|
||||||
paddingLeft: 10, //左边距离
|
|
||||||
paddingRight: 10, //右边距离
|
|
||||||
paddingTop: 0,
|
|
||||||
paddingBottom: 0,
|
|
||||||
marginLeft: 0,
|
|
||||||
marginRight: 0,
|
|
||||||
marginTop: 0,
|
|
||||||
marginBottom: 0,
|
|
||||||
backgroundColor: '#000000',
|
|
||||||
backAlpha: 0.5,
|
|
||||||
backRadius: 30 //背景圆角弧度
|
|
||||||
}
|
|
||||||
],
|
|
||||||
x: '100%', //x轴坐标
|
|
||||||
y: "50%", //y轴坐标
|
|
||||||
//position:[2,1,0],//位置[x轴对齐方式(0=左,1=中,2=右),y轴对齐方式(0=上,1=中,2=下),x轴偏移量(不填写或null则自动判断,第一个值为0=紧贴左边,1=中间对齐,2=贴合右边),y轴偏移量(不填写或null则自动判断,0=紧贴上方,1=中间对齐,2=紧贴下方)]
|
|
||||||
alpha: 1,
|
|
||||||
//backgroundColor:'#FFFFFF',
|
|
||||||
backAlpha: 0.8,
|
|
||||||
backRadius: 30 //背景圆角弧度
|
|
||||||
};
|
|
||||||
var danmu = player.addElement(danmuObj);
|
|
||||||
var danmuS = player.getElement(danmu);
|
|
||||||
var obj = {
|
|
||||||
element: danmu,
|
|
||||||
parameter: 'x',
|
|
||||||
static: true, //是否禁止其它属性,true=是,即当x(y)(alpha)变化时,y(x)(x,y)在播放器尺寸变化时不允许变化
|
|
||||||
effect: 'None.easeOut',
|
|
||||||
start: null,
|
|
||||||
end: -danmuS['width'],
|
|
||||||
speed: 10,
|
|
||||||
overStop: true,
|
|
||||||
pauseStop: true,
|
|
||||||
callBack: 'deleteChild'
|
|
||||||
};
|
|
||||||
var danmuAnimate = player.animate(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteChild(ele) {
|
|
||||||
if(player) {
|
|
||||||
player.deleteElement(ele);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeText(div, text) {
|
|
||||||
player.getByElement(div).innerHTML = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="http://www.chplayer.com/" target="_blank">官网chplayer.com</a>,版本号:1.0</p>
|
|
||||||
<p>以下仅列出部分功能,全部功能请至官网<a href="http://www.chplayer.com/manual/" target="_blank">《手册》</a>查看</p>
|
|
||||||
<p>
|
|
||||||
<button type="button" onclick="player.play()">播放</button>
|
|
||||||
<button type="button" onclick="player.pause()">暂停</button>
|
|
||||||
<button type="button" onclick="player.playOrPause()">播放/暂停</button>
|
|
||||||
<button type="button" onclick="loadedMetaDataHandler()">获取元数据</button>
|
|
||||||
<button type="button" onclick="newElement()">添加元件</button>
|
|
||||||
<button type="button" onclick="newDanmu()">添加弹幕</button>
|
|
||||||
<a href="http://www.chplayer.com/manual/animate.html" target="_blank">更多弹幕动作</a>
|
|
||||||
</p>
|
|
||||||
<p class="metadata"></p>
|
|
||||||
<p>单独监听功能:</p>
|
|
||||||
<p class="handler">
|
|
||||||
<span class="playstate">播放状态:暂停</span><br />
|
|
||||||
<span class="seekstate">无跳转时间</span><br />
|
|
||||||
<span class="volumechangestate">当前音量:0.8</span><br />
|
|
||||||
<span class="fullstate">是否全屏:否</span><br />
|
|
||||||
<span class="endedstate">还未结束</span><br />
|
|
||||||
<span class="videochangestate">视频地址正常</span><br />
|
|
||||||
<span class="currenttimestate">当前播放时间(秒):0</span>
|
|
||||||
</p>
|
|
@ -14,11 +14,11 @@ class Learning extends FrontendService
|
|||||||
|
|
||||||
use ChapterTrait;
|
use ChapterTrait;
|
||||||
|
|
||||||
public function handle()
|
public function handle($id)
|
||||||
{
|
{
|
||||||
$post = $this->request->getPost();
|
$post = $this->request->getPost();
|
||||||
|
|
||||||
$chapter = $this->checkChapterCache($post['chapter_id']);
|
$chapter = $this->checkChapterCache($id);
|
||||||
|
|
||||||
$user = $this->getLoginUser();
|
$user = $this->getLoginUser();
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ trait Auth
|
|||||||
|
|
||||||
$user->id = 0;
|
$user->id = 0;
|
||||||
$user->name = 'guest';
|
$user->name = 'guest';
|
||||||
|
$user->avatar = kg_ci_avatar_img_url(null);
|
||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"qcloudsms/qcloudsms_php": "0.1.*",
|
"qcloudsms/qcloudsms_php": "0.1.*",
|
||||||
"qcloud/cos-sdk-v5": "2.*",
|
"qcloud/cos-sdk-v5": "2.*",
|
||||||
"workerman/gateway-worker": "^3.0.12",
|
"workerman/gateway-worker": "^3.0.12",
|
||||||
|
"workerman/gatewayclient": "^3.0.12",
|
||||||
"whichbrowser/parser": "^2.0",
|
"whichbrowser/parser": "^2.0",
|
||||||
"hightman/xunsearch": "^1.4.14",
|
"hightman/xunsearch": "^1.4.14",
|
||||||
"aferrandini/phpqrcode": "1.0.1",
|
"aferrandini/phpqrcode": "1.0.1",
|
||||||
|
35
composer.lock
generated
35
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "1de77fca92539b23fbdbad81127bafd1",
|
"content-hash": "d847018715ab8103c3b5e04db1807223",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aferrandini/phpqrcode",
|
"name": "aferrandini/phpqrcode",
|
||||||
@ -1907,6 +1907,39 @@
|
|||||||
],
|
],
|
||||||
"time": "2019-07-02T11:55:24+00:00"
|
"time": "2019-07-02T11:55:24+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "workerman/gatewayclient",
|
||||||
|
"version": "v3.0.13",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/walkor/GatewayClient.git",
|
||||||
|
"reference": "6f4e76f38947be5cabca2c6fee367151f248d949"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/walkor/GatewayClient/zipball/6f4e76f38947be5cabca2c6fee367151f248d949",
|
||||||
|
"reference": "6f4e76f38947be5cabca2c6fee367151f248d949",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"GatewayClient\\": "./"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"homepage": "http://www.workerman.net",
|
||||||
|
"time": "2018-09-15T03:03:50+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "workerman/workerman",
|
"name": "workerman/workerman",
|
||||||
"version": "v3.5.22",
|
"version": "v3.5.22",
|
||||||
|
@ -727,6 +727,11 @@
|
|||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.live-player {
|
||||||
|
width: 800px;
|
||||||
|
height: 450px;
|
||||||
|
}
|
||||||
|
|
||||||
.chapter-bg {
|
.chapter-bg {
|
||||||
background-color: #f2f2f2;
|
background-color: #f2f2f2;
|
||||||
}
|
}
|
||||||
|
96
public/static/web/js/live.im.js
Normal file
96
public/static/web/js/live.im.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
layui.use(['jquery', 'layim'], function () {
|
||||||
|
|
||||||
|
var $ = layui.jquery;
|
||||||
|
var layim = layui.layim;
|
||||||
|
|
||||||
|
var socket = new WebSocket('ws://127.0.0.1:8282');
|
||||||
|
|
||||||
|
var membersUrl = $('input[name="im.members_url"]').val();
|
||||||
|
var bindUserUrl = $('input[name="im.bind_user_url"]').val();
|
||||||
|
var sendMsgUrl = $('input[name="im.send_msg_url"]').val();
|
||||||
|
|
||||||
|
var group = {
|
||||||
|
id: $('input[name="chapter.id"]').val(),
|
||||||
|
avatar: 'http://tp1.sinaimg.cn/5619439268/180/40030060651/1',
|
||||||
|
name: '直播讨论'
|
||||||
|
};
|
||||||
|
|
||||||
|
var user = {
|
||||||
|
id: $('input[name="user.id"]').val(),
|
||||||
|
name: $('input[name="user.name"]').val(),
|
||||||
|
avatar: $('input[name="user.avatar"]').val(),
|
||||||
|
status: 'online',
|
||||||
|
sign: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
layim.config({
|
||||||
|
brief: true,
|
||||||
|
init: {
|
||||||
|
mine: {
|
||||||
|
'username': user.name,
|
||||||
|
'avatar': user.avatar,
|
||||||
|
'id': user.id,
|
||||||
|
'status': user.status,
|
||||||
|
'sign': user.sign
|
||||||
|
}
|
||||||
|
},
|
||||||
|
members: {
|
||||||
|
url: membersUrl
|
||||||
|
}
|
||||||
|
}).chat({
|
||||||
|
type: 'group',
|
||||||
|
name: group.name,
|
||||||
|
avatar: group.avatar,
|
||||||
|
id: group.id
|
||||||
|
});
|
||||||
|
|
||||||
|
layim.on('sendMessage', function (res) {
|
||||||
|
sendMessage(res.mine, res.to);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.onopen = function () {
|
||||||
|
console.log('socket connect success');
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.onclose = function () {
|
||||||
|
console.log('socket connect close');
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.onerror = function () {
|
||||||
|
console.log('socket connect error');
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.onmessage = function (e) {
|
||||||
|
var data = JSON.parse(e.data);
|
||||||
|
console.log(data);
|
||||||
|
if (data.type === 'ping') {
|
||||||
|
socket.send('pong...');
|
||||||
|
} else if (data.type === 'bind_user') {
|
||||||
|
bindUser(data.client_id);
|
||||||
|
} else if (data.type === 'show_message') {
|
||||||
|
showMessage(data.content);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function bindUser(clientId) {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: bindUserUrl,
|
||||||
|
data: {client_id: clientId}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendMessage(from, to) {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
dataType: 'json',
|
||||||
|
url: sendMsgUrl,
|
||||||
|
data: {from: from, to: to}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMessage(message) {
|
||||||
|
layim.getMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
104
public/static/web/js/live.player.js
Normal file
104
public/static/web/js/live.player.js
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
var interval = null;
|
||||||
|
var intervalTime = 5000;
|
||||||
|
var position = 0;
|
||||||
|
var chapterId = $('input[name="chapter.id"]').val();
|
||||||
|
var planId = $('input[name="chapter.plan_id"]').val();
|
||||||
|
var userId = $('input[name="user.id"]').val();
|
||||||
|
var learningUrl = $('input[name="chapter.learning_url"]').val();
|
||||||
|
var playUrls = JSON.parse($('input[name="chapter.play_urls"]').val());
|
||||||
|
var requestId = getRequestId();
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
live: true,
|
||||||
|
autoplay: true,
|
||||||
|
h5_flv: true,
|
||||||
|
width: 800,
|
||||||
|
height: 450
|
||||||
|
};
|
||||||
|
|
||||||
|
if (playUrls.rtmp && playUrls.rtmp.od) {
|
||||||
|
options.rtmp = playUrls.rtmp.od;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playUrls.rtmp && playUrls.rtmp.hd) {
|
||||||
|
options.rtmp_hd = playUrls.rtmp.hd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playUrls.rtmp && playUrls.rtmp.sd) {
|
||||||
|
options.rtmp_sd = playUrls.rtmp.sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playUrls.flv && playUrls.flv.od) {
|
||||||
|
options.flv = playUrls.flv.od;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playUrls.flv && playUrls.flv.hd) {
|
||||||
|
options.flv_hd = playUrls.flv.hd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playUrls.flv && playUrls.flv.sd) {
|
||||||
|
options.flv_sd = playUrls.flv.sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playUrls.m3u8 && playUrls.m3u8.od) {
|
||||||
|
options.m3u8 = playUrls.m3u8.od;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playUrls.m3u8 && playUrls.m3u8.hd) {
|
||||||
|
options.m3u8_hd = playUrls.m3u8.hd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playUrls.m3u8 && playUrls.m3u8.sd) {
|
||||||
|
options.m3u8_sd = playUrls.m3u8.sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userId !== '0' && planId !== '0') {
|
||||||
|
options.listener = function (msg) {
|
||||||
|
if (msg.type === 'play') {
|
||||||
|
start();
|
||||||
|
} else if (msg.type === 'pause') {
|
||||||
|
stop();
|
||||||
|
} else if (msg.type === 'end') {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var player = new TcPlayer('player', options);
|
||||||
|
|
||||||
|
if (position > 0) {
|
||||||
|
player.currentTime(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
if (interval != null) {
|
||||||
|
clearInterval(interval);
|
||||||
|
interval = null;
|
||||||
|
}
|
||||||
|
interval = setInterval(learning, intervalTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
clearInterval(interval);
|
||||||
|
interval = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function learning() {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: learningUrl,
|
||||||
|
data: {
|
||||||
|
request_id: requestId,
|
||||||
|
chapter_id: chapterId,
|
||||||
|
plan_id: planId,
|
||||||
|
interval: intervalTime,
|
||||||
|
position: player.currentTime(),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRequestId() {
|
||||||
|
var id = Date.now().toString(36);
|
||||||
|
id += Math.random().toString(36).substr(3);
|
||||||
|
return id;
|
||||||
|
}
|
@ -38,8 +38,8 @@ class Events
|
|||||||
public static function onConnect($clientId)
|
public static function onConnect($clientId)
|
||||||
{
|
{
|
||||||
$message = json_encode([
|
$message = json_encode([
|
||||||
'type' => 'welcome',
|
'type' => 'bind_user',
|
||||||
'message' => 'just enjoy it',
|
'client_id' => $clientId,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Gateway::sendToClient($clientId, $message);
|
Gateway::sendToClient($clientId, $message);
|
||||||
@ -53,25 +53,7 @@ class Events
|
|||||||
*/
|
*/
|
||||||
public static function onMessage($clientId, $message)
|
public static function onMessage($clientId, $message)
|
||||||
{
|
{
|
||||||
$content = json_decode($message, true);
|
|
||||||
|
|
||||||
if (!isset($content['type'])) return;
|
|
||||||
|
|
||||||
if ($content['type'] == 'join_group') {
|
|
||||||
|
|
||||||
$_SESSION['group'] = $content['group'];
|
|
||||||
|
|
||||||
Gateway::joinGroup($clientId, $content['group']);
|
|
||||||
|
|
||||||
} elseif ($content['type'] == 'send_danmaku') {
|
|
||||||
|
|
||||||
$message = [
|
|
||||||
'type' => 'show_danmaku',
|
|
||||||
'danmaku' => $content['danmaku'],
|
|
||||||
];
|
|
||||||
|
|
||||||
Gateway::sendToGroup($_SESSION['group'], json_encode($message), [$clientId]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user