Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Z
zuiketang
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
夏彬
zuiketang
Commits
98b9beca
Commit
98b9beca
authored
Oct 26, 2016
by
xiabin
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/dev' into dev
parents
846ee92f
74189245
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
623 additions
and
112 deletions
+623
-112
CourseController.php
src/backend/controllers/CourseController.php
+14
-8
QiniuTranscode.php
src/common/libs/QiniuTranscode.php
+217
-0
Course.php
src/common/models/Course.php
+1
-1
Courseware.php
src/common/models/Courseware.php
+1
-58
TranscodeQueue.php
src/common/models/TranscodeQueue.php
+183
-0
m161026_085127_transcode_queue.php
src/console/migrations/m161026_085127_transcode_queue.php
+43
-0
QiniuCallbackController.php
src/frontend/controllers/QiniuCallbackController.php
+98
-14
main.css
src/frontend/web/css/main.css
+47
-23
video-intro.vue
src/frontend/web/js/home/components/video-intro.vue
+18
-7
video-play.vue
src/frontend/web/js/home/components/video-play.vue
+1
-1
No files found.
src/backend/controllers/CourseController.php
View file @
98b9beca
...
...
@@ -13,6 +13,7 @@ use common\libs\Utils;
use
common\models\Classes
;
use
common\models\Course
;
use
common\models\Courseware
;
use
common\models\TranscodeQueue
;
use
common\models\User
;
use
Yii
;
use
yii\base\ExitException
;
...
...
@@ -83,18 +84,21 @@ class CourseController extends Controller
case
Course
::
STATUS_TRANSCODING
:
if
(
$check
==
Course
::
STATUS_TRANSCODING
)
{
//如果该内容课件已经拥有转码后的标准内容,则不再进行转码,直接进入已审核状态
if
(
!
$courseware
->
src_stand
)
{
if
(
$courseware
->
src_stand
)
{
$check
=
Course
::
STATUS_OK
;
}
else
{
//发起转码流程
if
(
!
Courseware
::
sendTranscodeSignal
(
$courseware
))
{
Utils
::
ajaxResponse
(
false
,
'审核失败,发送转码请求失败!'
);
$result
=
TranscodeQueue
::
sendTranscodeSignal
(
$course
,
$courseware
);
if
(
$result
===
false
)
{
Utils
::
ajaxResponse
(
false
,
TranscodeQueue
::
$lastError
);
}
elseif
(
$result
===
null
)
{
$check
=
Course
::
STATUS_OK
;
}
}
}
$course
->
status
=
$check
;
$courseware
->
status
=
Courseware
::
STATUS_OK
;
$courseware
->
status
=
$check
;
if
(
$course
->
save
()
&&
$courseware
->
save
()
&&
$msg
)
{
$template
=
Yii
::
$app
->
params
[
'course.check.msg.ok'
];
...
...
@@ -147,18 +151,20 @@ class CourseController extends Controller
public
function
actionSig
()
{
$courseware
=
Courseware
::
findOne
([
'course_id'
=>
7
]);
$courseware
=
Courseware
::
findOne
([
'course_id'
=>
6
]);
if
(
!
$courseware
)
{
throw
new
ExitException
(
'Courseware not found!'
);
}
$course
=
Course
::
findOne
([
'id'
=>
$courseware
->
course_id
]);
print_r
(
$courseware
->
toArray
());
$res
=
Courseware
::
sendTranscodeSignal
(
$courseware
);
$res
=
TranscodeQueue
::
sendTranscodeSignal
(
$course
,
$courseware
);
if
(
!
$res
)
{
echo
Coursewar
e
::
$lastError
;
echo
TranscodeQueu
e
::
$lastError
;
}
}
...
...
src/common/libs/QiniuTranscode.php
0 → 100644
View file @
98b9beca
<?php
/**
* Created by PhpStorm.
* User: pader
* Date: 2016/10/26
* Time: 11:15
*/
namespace
common\libs
;
use
Qiniu\Processing\PersistentFop
;
use
Qiniu\Storage\BucketManager
;
use
yii\helpers\Url
;
/**
* 七牛转码类
*
* @package common\libs
*/
class
QiniuTranscode
{
public
static
$lastError
;
const
TARGET_FORMAT
=
'mp4'
;
/**
* 发送指定课件的转码信号
*
* @param string $sourceKey
* @param string $targetKey
* @return string|boolean 成功返回处理的 presistentId 或者返回 false
*/
public
static
function
startTranscode
(
$sourceKey
,
$targetKey
)
{
/* @var $qiniu \common\components\Qiniu */
$qiniu
=
\Yii
::
$app
->
qiniu
;
$auth
=
$qiniu
->
getAuthInstance
();
//获取视频元信息,对比与目标格式的区别
$baseUrl
=
$qiniu
->
getStorageConfig
(
'video'
,
'url'
)
.
$sourceKey
;
$avUrl
=
$auth
->
privateDownloadUrl
(
$baseUrl
.
'?avinfo'
);
$response
=
\Qiniu\Http\Client
::
get
(
$avUrl
);
$avInfo
=
$response
->
json
();
if
(
!
$avInfo
)
{
self
::
$lastError
=
'获取视频文件信息失败'
;
}
if
(
isset
(
$avInfo
[
'error'
]))
{
self
::
$lastError
=
$avInfo
[
'error'
];
return
false
;
}
$fops
=
self
::
transcodeFops
(
$avInfo
);
$bucket
=
$qiniu
->
getStorageConfig
(
'video'
,
'bucket'
);
//存储位置
$target
=
$bucket
.
':'
.
$targetKey
;
$notifyUrl
=
YII_ENV
==
'dev'
?
'http://t.pp.cc/tmp/qiniu_callback.php'
:
Url
::
to
([
'qiniu-callback/transcode'
],
true
);;
/* @var $err null|\Qiniu\Http\Error */
if
(
$fops
)
{
$fops
.=
'|saveas/'
.
\Qiniu\base64_urlSafeEncode
(
$target
);
//发送处理请求
$persistent
=
new
PersistentFop
(
$auth
,
$bucket
,
null
,
$notifyUrl
);
list
(
$presistendId
,
$err
)
=
$persistent
->
execute
(
$sourceKey
,
$fops
);
if
(
$err
)
{
self
::
$lastError
=
$err
;
return
false
;
}
else
{
return
$presistendId
;
}
}
else
{
//不需要转换时则直接拷贝资源
$bucketMgr
=
new
BucketManager
(
$auth
);
$err
=
$bucketMgr
->
copy
(
$bucket
,
$sourceKey
,
$bucket
,
$targetKey
);
if
(
$err
)
{
self
::
$lastError
=
$err
->
message
();
return
false
;
}
return
true
;
}
}
/**
* 生成免费视频
*
* @param string $standKey
* @param string $targetKey
* @param int $freeTime 免费分钟数
* @return string|bool
*/
public
static
function
transFreeVideo
(
$standKey
,
$targetKey
,
$freeTime
)
{
/* @var $qiniu \common\components\Qiniu */
$qiniu
=
\Yii
::
$app
->
qiniu
;
$auth
=
$qiniu
->
getAuthInstance
();
$bucket
=
$qiniu
->
getStorageConfig
(
'video'
,
'bucket'
);
//获取视频元信息,对比与目标格式的区别
$baseUrl
=
$qiniu
->
getStorageConfig
(
'video'
,
'url'
)
.
$standKey
;
$avUrl
=
$auth
->
privateDownloadUrl
(
$baseUrl
.
'?avinfo'
);
$response
=
\Qiniu\Http\Client
::
get
(
$avUrl
);
$avInfo
=
$response
->
json
();
if
(
!
$avInfo
)
{
self
::
$lastError
=
'获取视频文件信息失败'
;
}
if
(
isset
(
$avInfo
[
'error'
]))
{
self
::
$lastError
=
$avInfo
[
'error'
];
return
false
;
}
$fops
=
self
::
transcodeFops
(
$avInfo
,
true
);
//存储位置
$target
=
$bucket
.
':'
.
$targetKey
;
$fops
=
$fops
.
'/ss/0/t/'
.
(
$freeTime
*
60
)
.
'|saveas/'
.
\Qiniu\base64_urlSafeEncode
(
$target
);
$notifyUrl
=
YII_ENV
==
'dev'
?
'http://t.pp.cc/tmp/qiniu_callback.php'
:
Url
::
to
([
'qiniu-callback/transcode'
],
true
);;
//发送处理请求
/* @var $err null|\Qiniu\Http\Error */
$persistent
=
new
PersistentFop
(
$auth
,
$bucket
,
null
,
$notifyUrl
);
list
(
$presistendId
,
$err
)
=
$persistent
->
execute
(
$standKey
,
$fops
);
if
(
$err
)
{
self
::
$lastError
=
$err
->
message
();
return
false
;
}
return
$presistendId
;
}
/**
* 对比并返回
*
* @param array $avInfo
* @param bool $force
* @return string
*/
public
static
function
transcodeFops
(
$avInfo
,
$force
=
false
)
{
//转换目录最大参数
$target
=
[
'width'
=>
1280
,
//分辨率
'height'
=>
720
,
'ab'
=>
'64k'
,
//音频码率
'ar'
=>
44100
,
//音频采样率
'vb'
=>
1950
*
1000
,
//视频码率1950k
'vcodec'
=>
'libx264'
,
//视频编码方案
'acodec'
=>
'aac'
,
//音频编码方案
'fps'
=>
30
//FPS
];
list
(
$video
,
$audio
)
=
$avInfo
[
'streams'
];
$fopsMain
=
''
;
//必要参数,当必要参数具备时一定转换编码
$fopsAddon
=
'/ab/'
.
$target
[
'ab'
];
//非必要参数,只有必要参数具备,非必要参数才会作为附属添加进去
//音频采样率对比
if
(
$audio
[
'sample_rate'
]
>
$target
[
'ar'
])
{
$fopsAddon
.=
'/ar/'
.
$target
[
'ar'
];
}
//视频采样率对比
//if ($video['bit_rate'] > $target['vb']) {
$fopsAddon
.=
'/vb/'
.
$target
[
'vb'
];
//}
//编码对比
if
(
$video
[
'codec_name'
]
!=
'h264'
)
{
$fopsMain
.=
'/vcodec/'
.
$target
[
'vcodec'
];
}
if
(
$audio
[
'codec_name'
]
!=
'aac'
)
{
$fopsMain
.=
'/acodec/'
.
$target
[
'acodec'
];
}
//FPS 对比
$fpsRate
=
explode
(
'/'
,
$video
[
'r_frame_rate'
]);
if
(
$fpsRate
[
'0'
]
>
$target
[
'fps'
])
{
$fopsMain
.=
'/r/'
.
$target
[
'fps'
];
}
//分辨率对比,以原比例限定在指定分辨率以内
if
(
$force
)
{
$fopsMain
.=
'/s/'
.
(
$video
[
'width'
]
>
$target
[
'width'
]
?
$target
[
'width'
]
:
$video
[
'width'
])
.
'x'
.
(
$video
[
'height'
]
>
$target
[
'height'
]
?
$target
[
'height'
]
:
$video
[
'height'
])
.
'/autoscale/1'
;
}
elseif
(
$video
[
'width'
]
>
$target
[
'width'
]
||
$video
[
'height'
]
>
$target
[
'height'
])
{
$fopsMain
.=
'/s/'
.
$target
[
'width'
]
.
'x'
.
$target
[
'height'
]
.
'/autoscale/1'
;
}
$fops
=
''
;
//如果视频不是目标格式,或有必要参数,则进行转码
if
(
$force
||
strpos
(
$avInfo
[
'format'
][
'format_name'
],
self
::
TARGET_FORMAT
)
===
false
)
{
$fops
=
'avthumb/'
.
self
::
TARGET_FORMAT
.
$fopsMain
.
$fopsAddon
;
}
return
$fops
;
}
}
\ No newline at end of file
src/common/models/Course.php
View file @
98b9beca
...
...
@@ -90,7 +90,7 @@ class Course extends \yii\db\ActiveRecord
[
'free_time'
,
'integer'
,
'min'
=>
0
,
'max'
=>
15
],
[
'recommend'
,
'boolean'
],
[[
'recommend'
,
'comment_count'
,
'favorite_count'
,
'support_count'
,
'play_count'
],
'default'
,
'value'
=>
0
],
[
'status'
,
'in'
,
'range'
=>
[
0
,
1
,
2
,
3
]]
[
'status'
,
'in'
,
'range'
=>
[
0
,
1
,
2
,
3
,
4
]]
];
}
...
...
src/common/models/Courseware.php
View file @
98b9beca
...
...
@@ -30,8 +30,6 @@ class Courseware extends ActiveRecord
const
STATUS_FAILED
=
2
;
const
STATUS_LOCKED
=
3
;
public
static
$lastError
=
''
;
/**
* @inheritdoc
*/
...
...
@@ -109,60 +107,5 @@ class Courseware extends ActiveRecord
$result
=
self
::
find
()
->
select
(
'id'
)
->
where
(
'id=:id'
,
[
':id'
=>
$id
])
->
one
();
return
$result
===
NULL
?
FALSE
:
TRUE
;
}
/**
* 发送指定课件的转码信号
*
* @param Courseware $courseware
* @return bool
*/
public
static
function
sendTranscodeSignal
(
$courseware
)
{
//非视频不可发送转码请求
if
(
$courseware
->
type
!=
0
)
{
self
::
$lastError
=
'视频不可发送转码请求'
;
return
false
;
}
//已有转码后的视频不可再发送转码请求
if
(
$courseware
->
src_stand
)
{
self
::
$lastError
=
'已有转码后的视频不可再发送转码请求'
;
return
false
;
}
/**
* @var $qiniu \common\components\Qiniu
*/
$qiniu
=
\Yii
::
$app
->
qiniu
;
$auth
=
$qiniu
->
getAuthInstance
();
//获取视频元信息,对比与目标格式的区别
$baseUrl
=
$qiniu
->
getStorageConfig
(
'video'
,
'url'
)
.
$courseware
->
name
;
$avUrl
=
$auth
->
privateDownloadUrl
(
$baseUrl
.
'?avinfo'
);
$response
=
\Qiniu\Http\Client
::
get
(
$avUrl
);
$avInfo
=
$response
->
json
();
if
(
!
$avInfo
)
{
self
::
$lastError
=
'获取视频文件信息失败'
;
}
if
(
isset
(
$avInfo
[
'error'
]))
{
self
::
$lastError
=
$avInfo
[
'error'
];
return
false
;
}
list
(
$video
,
$audio
)
=
$avInfo
[
'streams'
];
exit
;
$bucket
=
$qiniu
->
getStorageConfig
(
'video'
,
'bucket'
);
$fops
=
''
;
$notifyUrl
=
'http://t.pp.cc/tmp/qiniu_callback.php'
;
$persistent
=
new
\Qiniu\Processing\PersistentFop
(
$auth
,
$bucket
,
null
,
$notifyUrl
);
$$persistent
->
execute
(
$courseware
->
name
,
$fops
);
}
}
src/common/models/TranscodeQueue.php
0 → 100644
View file @
98b9beca
<?php
namespace
common\models
;
use
common\libs\QiniuTranscode
;
use
common\libs\Utils
;
use
Yii
;
use
yii\behaviors\TimestampBehavior
;
use
yii\db\ActiveRecord
;
/**
* This is the model class for table "transcode_queue".
*
* @property string $id
* @property integer $course_id
* @property integer $courseware_id
* @property string $type
* @property string $src
* @property string $target
* @property int $status
* @property integer $created_at
* @property integer $updated_at
*/
class
TranscodeQueue
extends
ActiveRecord
{
const
STATUS_WAIT
=
0
;
//进行等待中
const
STATUS_DONE
=
1
;
//已完成
//const STATUS_DISCARD = 2;
public
static
$lastError
=
''
;
/**
* @inheritdoc
*/
public
static
function
tableName
()
{
return
'transcode_queue'
;
}
/**
* @inheritdoc
*/
public
function
rules
()
{
return
[
[[
'id'
,
'course_id'
,
'courseware_id'
,
'type'
,
'src'
,
'target'
],
'required'
],
[[
'course_id'
,
'courseware_id'
,
'status'
,
'created_at'
,
'updated_at'
],
'integer'
],
[[
'id'
,
'type'
],
'string'
]
];
}
/**
* @inheritdoc
*/
public
function
attributeLabels
()
{
return
[
'id'
=>
'ID'
,
'course_id'
=>
'Course ID'
,
'courseware_id'
=>
'Courseware ID'
,
'type'
=>
'Type'
,
'src'
=>
'Src'
,
'target'
=>
'Target'
,
'status'
=>
'Status'
,
'created_at'
=>
'Created At'
,
'updated_at'
=>
'Updated At'
,
];
}
/**
* @inheritdoc
*/
public
function
behaviors
()
{
return
[
[
'class'
=>
TimestampBehavior
::
className
(),
'attributes'
=>
[
ActiveRecord
::
EVENT_BEFORE_INSERT
=>
[
'created_at'
,
'updated_at'
],
ActiveRecord
::
EVENT_BEFORE_UPDATE
=>
[
'updated_at'
],
]
]
];
}
/**
* 发送指定课件的转码信号
*
* 进入队列后,一旦转码完成,通知会自动理发课程与课件的状态为已审核
*
* @param Course $course
* @param Courseware $courseware
* @return bool|null 返回null代表转码完成,true代表进入队列,false代表失败
*/
public
static
function
sendTranscodeSignal
(
$course
,
$courseware
)
{
//非视频不可发送转码请求
if
(
$courseware
->
type
!=
0
)
{
self
::
$lastError
=
'视频不可发送转码请求'
;
return
false
;
}
//已有转码后的视频不可再发送转码请求
if
(
$courseware
->
src_stand
)
{
self
::
$lastError
=
'已有转码后的视频不可再发送转码请求'
;
return
false
;
}
/* @var $qiniu \common\components\Qiniu */
$qiniu
=
\Yii
::
$app
->
qiniu
;
$srcStand
=
'stand/'
.
$qiniu
->
generateRandomFilePath
(
'.'
.
QiniuTranscode
::
TARGET_FORMAT
);;
$result
=
QiniuTranscode
::
startTranscode
(
$courseware
->
name
,
$srcStand
);
if
(
$result
===
false
)
{
self
::
$lastError
=
QiniuTranscode
::
$lastError
;
return
false
;
}
//返回 true 为直接拷贝完成的情况,否则为进入了转码队列中
if
(
$result
===
true
)
{
if
(
$courseware
->
src_stand
&&
$courseware
->
src_stand
!=
$srcStand
)
{
UploadPools
::
deleteFile
(
'video:'
.
$courseware
->
src_stand
);
}
$courseware
->
src_stand
=
$srcStand
;
$courseware
->
save
();
//如果有免费时间,发起截取转码免费部分的请求
if
(
$course
->
free_time
>
0
)
{
return
(
bool
)
self
::
sendFreeTranscodeSignal
(
$courseware
->
course_id
,
$courseware
->
id
,
$srcStand
,
$course
->
free_time
);
}
return
null
;
}
else
{
//进入队列
$queue
=
new
self
();
$queue
->
id
=
$result
;
$queue
->
course_id
=
$courseware
->
course_id
;
$queue
->
courseware_id
=
$courseware
->
id
;
$queue
->
type
=
'stand'
;
$queue
->
src
=
$courseware
->
name
;
$queue
->
target
=
$srcStand
;
if
(
!
$queue
->
save
())
{
self
::
$lastError
=
Utils
::
fetchErrorFirst
(
$queue
->
errors
);
return
false
;
}
return
true
;
}
}
public
static
function
sendFreeTranscodeSignal
(
$courseId
,
$coursewareId
,
$srcStand
,
$freeTime
)
{
/* @var $qiniu \common\components\Qiniu */
$qiniu
=
\Yii
::
$app
->
qiniu
;
$srcFree
=
'free/'
.
$qiniu
->
generateRandomFilePath
(
'.'
.
QiniuTranscode
::
TARGET_FORMAT
);
$presistendId
=
QiniuTranscode
::
transFreeVideo
(
$srcStand
,
$srcFree
,
$freeTime
);
if
(
$presistendId
==
false
)
{
self
::
$lastError
=
'免费视频转码请求发送失败:'
.
QiniuTranscode
::
$lastError
;
return
false
;
}
$newQueue
=
new
TranscodeQueue
();
$newQueue
->
id
=
$presistendId
;
$newQueue
->
course_id
=
$courseId
;
$newQueue
->
courseware_id
=
$coursewareId
;
$newQueue
->
type
=
'free'
;
$newQueue
->
src
=
$srcStand
;
$newQueue
->
target
=
$srcFree
;
if
(
!
$newQueue
->
save
())
{
self
::
$lastError
=
Utils
::
fetchErrorFirst
(
$newQueue
->
errors
);
return
false
;
}
return
$newQueue
;
}
}
src/console/migrations/m161026_085127_transcode_queue.php
0 → 100644
View file @
98b9beca
<?php
use
yii\db\Migration
;
class
m161026_085127_transcode_queue
extends
Migration
{
public
$table
=
'{{%ranscode_queue}}'
;
public
function
up
()
{
$this
->
createTable
(
$this
->
table
,
[
'`id` varchar(50) NOT NULL'
,
'course_id'
=>
$this
->
integer
(
10
)
->
unsigned
()
->
notNull
(),
'courseware_id'
=>
$this
->
integer
(
10
)
->
unsigned
()
->
notNull
(),
'`type` enum(\'stand\',\'free\') NOT NULL'
,
'src'
=>
$this
->
string
(
200
)
->
notNull
()
->
comment
(
'源视频'
),
'target'
=>
$this
->
string
(
200
)
->
notNull
()
->
comment
(
'视频'
),
'`status` tinyint(1) NOT NULL DEFAULT \'0\' COMMENT \'状态:0转换中,1已完成\''
,
'created_at'
=>
$this
->
integer
(
10
)
->
unsigned
()
->
notNull
(),
'updated_at'
=>
$this
->
integer
(
10
)
->
unsigned
()
->
notNull
(),
'PRIMARY KEY (`id`)'
]);
$this
->
addCommentOnTable
(
$this
->
table
,
'转码队列表'
);
}
public
function
down
()
{
$this
->
dropTable
(
$this
->
table
);
}
/*
// Use safeUp/safeDown to run migration code within a transaction
public function safeUp()
{
}
public function safeDown()
{
}
*/
}
src/frontend/controllers/QiniuCallbackController.php
View file @
98b9beca
...
...
@@ -7,6 +7,11 @@
*/
namespace
frontend\controllers
;
use
common\libs\QiniuTranscode
;
use
common\libs\Utils
;
use
common\models\Course
;
use
common\models\Courseware
;
use
common\models\TranscodeQueue
;
use
common\models\UploadPools
;
use
Yii
;
use
yii\web\Response
;
...
...
@@ -23,20 +28,7 @@ class QiniuCallbackController extends \yii\web\Controller
*/
public
function
actionRemUpload
()
{
/* @var \Qiniu\Auth $auth */
$auth
=
Yii
::
$app
->
qiniu
->
getAuthInstance
();
$response
=
Yii
::
$app
->
response
;
$response
->
format
=
Response
::
FORMAT_JSON
;
//验证回调请求
$requestBody
=
file_get_contents
(
'php://input'
);
$authorization
=
isset
(
$_SERVER
[
'HTTP_AUTHORIZATION'
])
?
$_SERVER
[
'HTTP_AUTHORIZATION'
]
:
''
;
$currentUrl
=
YII_ENV
==
'dev'
?
'http://t.pp.cc/tmp/qiniu_callback.php'
:
Yii
::
$app
->
request
->
hostInfo
.
Yii
::
$app
->
request
->
getUrl
();
if
(
!
$auth
->
verifyCallback
(
$_SERVER
[
'CONTENT_TYPE'
],
$authorization
,
$currentUrl
,
$requestBody
))
{
if
(
!
$this
->
verifyCallback
())
{
return
[
'error'
=>
'回调验证失败!'
];
}
...
...
@@ -67,6 +59,71 @@ class QiniuCallbackController extends \yii\web\Controller
}
}
/**
* 接收转码回调
*
* @return array
*/
public
function
actionTranscode
()
{
$post
=
Yii
::
$app
->
request
->
getRawBody
();
$data
=
json_decode
(
$post
,
true
);
if
(
!
is_array
(
$data
))
{
return
[
'error'
=>
'回调数据格式错误!'
];
}
if
(
!
empty
(
$data
[
'error'
]))
{
Yii
::
error
(
$data
[
'error'
]);
return
[
'error'
=>
true
];
}
if
(
!
isset
(
$data
[
'id'
])
||
!
isset
(
$data
[
'items'
]))
{
return
[
'error'
=>
'数据格式错误'
];
}
$queue
=
TranscodeQueue
::
findOne
([
'id'
=>
$data
[
'id'
]]);
if
(
!
$queue
)
{
return
[
'error'
=>
'该本地队列不存在!'
];
}
$course
=
Course
::
findOne
([
'id'
=>
$queue
->
course_id
]);
$courseware
=
Courseware
::
findOne
([
'id'
=>
$queue
->
courseware_id
]);
$srcField
=
$queue
->
type
==
'stand'
?
'src_stand'
:
'src_free'
;
//$comeKey = $data['items'][0]['key'];
if
(
$courseware
->
$srcField
&&
$courseware
->
$srcField
!=
$queue
[
'target'
])
{
UploadPools
::
deleteFile
(
'video:'
.
$courseware
->
$srcField
);
}
$courseware
->
$srcField
=
$queue
[
'target'
];
//确认完成
$queue
->
status
=
TranscodeQueue
::
STATUS_DONE
;
$queue
->
save
();
//如果还有免费视频则处理免费视频
if
(
$queue
->
type
==
'stand'
&&
$course
->
free_time
>
0
)
{
$freeResult
=
TranscodeQueue
::
sendFreeTranscodeSignal
(
$courseware
->
course_id
,
$courseware
->
id
,
$queue
[
'target'
],
$course
->
free_time
);
if
(
!
$freeResult
)
{
return
[
'error'
=>
TranscodeQueue
::
$lastError
];
}
}
else
{
$courseware
->
status
=
Courseware
::
STATUS_OK
;
$course
->
status
=
Course
::
STATUS_OK
;
}
if
(
$queue
->
status
==
TranscodeQueue
::
STATUS_DONE
||
$course
->
status
==
Course
::
STATUS_OK
)
{
$courseware
->
save
();
$course
->
save
();
}
return
[
'error'
=>
false
];
}
/**
* 响应回调成功的信息
*
...
...
@@ -93,4 +150,31 @@ class QiniuCallbackController extends \yii\web\Controller
return
$return
;
}
/**
* 检查七牛回调是否通过
*
* @return bool
*/
private
function
verifyCallback
()
{
/* @var \Qiniu\Auth $auth */
$auth
=
Yii
::
$app
->
qiniu
->
getAuthInstance
();
$response
=
Yii
::
$app
->
response
;
$response
->
format
=
Response
::
FORMAT_JSON
;
//验证回调请求
$requestBody
=
file_get_contents
(
'php://input'
);
$authorization
=
isset
(
$_SERVER
[
'HTTP_AUTHORIZATION'
])
?
$_SERVER
[
'HTTP_AUTHORIZATION'
]
:
''
;
$currentUrl
=
YII_ENV
==
'dev'
?
'http://t.pp.cc/tmp/qiniu_callback.php'
:
Yii
::
$app
->
request
->
hostInfo
.
Yii
::
$app
->
request
->
getUrl
();
if
(
!
$auth
->
verifyCallback
(
$_SERVER
[
'CONTENT_TYPE'
],
$authorization
,
$currentUrl
,
$requestBody
))
{
return
false
;
}
return
true
;
}
}
\ No newline at end of file
src/frontend/web/css/main.css
View file @
98b9beca
...
...
@@ -424,8 +424,8 @@ a,a:hover,a:link {
width
:
100%
;
left
:
0
;
top
:
0
;
height
:
1
8
0px
;
line-height
:
1
8
0px
;
height
:
1
5
0px
;
line-height
:
1
5
0px
;
text-align
:
center
;
font-size
:
64px
;
color
:
#fff
;
...
...
@@ -507,6 +507,7 @@ a,a:hover,a:link {
background-color
:
#fff
;
border
:
1px
solid
#f3f3f3
;
border-top
:
none
;
padding-left
:
10px
;
}
.video-teacher
{
padding
:
10px
;
...
...
@@ -538,7 +539,7 @@ a,a:hover,a:link {
.video-sm-info
{
height
:
80px
;
line-height
:
80px
;
padding-right
:
3
0px
;
padding-right
:
2
0px
;
}
.video-sm-info
a
{
display
:
inline-block
;
...
...
@@ -559,26 +560,22 @@ a,a:hover,a:link {
line-height
:
30px
;
top
:
0
;
left
:
0
;
font-size
:
30
px
;
font-size
:
24
px
;
}
/*video detail*/
.warp-box
{
background-color
:
#fff
;
margin-top
:
4
0px
;
margin-top
:
2
0px
;
padding
:
20px
0
;
border-top
:
1px
solid
#f3f3f3
;
}
.video-description
.title
{
font-size
:
16px
;
color
:
#333
;
padding-bottom
:
10px
;
}
.video-description
.text
{
color
:
#999
;
}
.video-description
.text
img
{
max-width
:
100%
;
height
:
auto
;
border
:
none
;
vertical-align
:
top
;
}
...
...
@@ -586,10 +583,14 @@ a,a:hover,a:link {
.video-comment
{
margin-top
:
30px
;
}
.video-description
.title
,
.video-comment
.title
{
font-size
:
16px
;
color
:
#333
;
padding-bottom
:
10px
;
padding-left
:
10px
;
border-left
:
3px
solid
#3f7de4
;
margin-bottom
:
20px
;
margin-top
:
20px
;
}
.video-comment
.title
small
{
font-size
:
12px
;
...
...
@@ -608,30 +609,49 @@ a,a:hover,a:link {
}
.comment-box
{
position
:
relative
;
padding-left
:
60px
;
margin-top
:
20px
;
padding-bottom
:
40px
;
margin-bottom
:
40px
;
}
.comment-head
img
{
width
:
50
px
;
height
:
50
px
;
width
:
34
px
;
height
:
34
px
;
border-radius
:
100%
;
}
.comment-head
{
position
:
absolute
;
left
:
0
;
top
:
0
;
padding-right
:
10px
;
padding
:
10px
;
}
.comment-head
span
{
display
:
inline-block
;
height
:
34px
;
line-height
:
34px
;
}
.comment-input
{
display
:
block
;
border
:
1px
solid
#e7e7e7
;
}
.comment-input
textarea
{
height
:
50px
;
height
:
80px
;
border
:
none
;
box-shadow
:
none
;
border-radius
:
inherit
;
width
:
100%
;
vertical-align
:
top
;
outline
:
none
;
}
.textarea-box
{
padding
:
10px
;
}
.btn
{
outline
:
none
;
}
.comment-foot
{
border-top
:
1px
solid
#f3f3f3
;
}
.m-t-10
{
margin-top
:
10px
;
}
.m-r-10
{
margin-right
:
10px
;
}
.m-l-20
{
margin-left
:
20px
;
}
...
...
@@ -643,16 +663,20 @@ a,a:hover,a:link {
width
:
50px
;
border-radius
:
100%
;
}
.user-i
span
,
.user-i
span
small
{
.user-i
span
{
font-size
:
14px
;
color
:
#999
;
}
.user-i
span
small
{
font-size
:
12px
;
color
:
#999
;
}
.user-i
span
small
{
padding-left
:
5px
;
}
.user-i
p
{
padding-top
:
5px
;
font-size
:
14px
;
}
.comment-main-list
{
margin-bottom
:
40px
;
...
...
src/frontend/web/js/home/components/video-intro.vue
View file @
98b9beca
...
...
@@ -13,21 +13,32 @@
<
small
>
{{
coursewareInfo
.
comment_count
}}
<
/small
>
<
/div
>
<
/div
>
<
div
v
-
if
=
"coursewareInfo.isGuest"
class
=
"comment-login"
>
<
!--
<
div
v
-
if
=
"coursewareInfo.isGuest"
class
=
"comment-login"
>
需要
<
a
@
click
=
"login"
href
=
"javascript:;"
>
登录
<
/a> 才能评
论
<
/div
>
<
/div>
--
>
<
div
v
-
else
class
=
"comment-box"
>
<
div
class
=
"comment-input"
>
<
textarea
v
-
model
=
"content"
cols
=
"30"
rows
=
"10"
class
=
"form-control"
placeholder
=
"说几句吧,亲..."
><
/textarea
>
<
div
class
=
"textarea-box"
>
<
textarea
v
-
model
=
"content"
cols
=
"30"
rows
=
"10"
placeholder
=
"说几句吧,亲..."
><
/textarea
>
<
/div
>
<
div
v
-
if
=
"coursewareInfo.isGuest"
class
=
"comment-foot clearfix"
>
<
div
class
=
"comment-head pull-left"
>
<
span
>
需要
<
a
@
click
=
"login"
href
=
"javascript:;"
>
登录
<
/a> 才能评论</
span
>
<
/div
>
<
button
@
click
=
"comment"
class
=
"btn btn-info pull-right m-t-10 m-r-10"
disabled
=
"disabled"
>
发表评论
<
/button
>
<
/div
>
<
div
v
-
else
class
=
"comment-foot clearfix"
>
<
div
class
=
"comment-foot clearfix"
>
<
div
class
=
"comment-head pull-left"
>
<
div
class
=
"comment-head pull-left"
>
<
img
:
src
=
"coursewareInfo.userAvatar"
>
<
/div
>
<
button
@
click
=
"comment"
class
=
"btn btn-
default pull-right m-t
-10"
>
发表评论
<
/button
>
<
button
@
click
=
"comment"
class
=
"btn btn-
primary pull-right m-t-10 m-r
-10"
>
发表评论
<
/button
>
<
/div
>
<
/div
>
...
...
src/frontend/web/js/home/components/video-play.vue
View file @
98b9beca
...
...
@@ -30,7 +30,7 @@
</button>
<template v-else>
<button v-if="
coursewareInfo
.
isShop
" class="
btn
btn
-
danger
m
-
l
-
20
hidden
-
xs
mb
-
left
"
data-toggle="
modal
">已购买
data-toggle="
modal
"
disabled="
disabled
"
>已购买
</button>
<template v-else>
<button v-if="
isMobile
===
false
&&
isWeixin
===
false
" class="
btn
btn
-
danger
m
-
l
-
20
mb
-
left
"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment