手把手教你做短视频去水印微信小程序(5-服务端代码)
文章目录
- 手把手教你做短视频去水印微信小程序(5-服务端代码)
- 前言
- 一、框架
- 二、登陆/退出接口
- 2.1 路由
- 2.2 控制器
- 三、视频解析、解析记录接口
- 3.1 路由
- 3.2 控制器
- 3.2.1 视频地址解析
- 3.2.2 解析记录controller
- 三、nginx代理下载配置
- 总结
- github源码地址
前言
前边几篇文章我们介绍了小程序端关键代码,这一篇我们来说一下服务端代码。这里主要借助一个开源项目 smalls/video-tools 来实现视频解析的核心部分,在此基础上,我们实现api接口以供调用。
一、框架
这里我选用我最为熟悉的php语言开发框架:Laravel
目前laravel版本已经到了 8.x
,这里我使用的是长期支持版 6.x
快速开始请见github的 readme.md
文档。
有关框架的使用在此不做介绍,有不熟悉的同学可以查阅官方文档,laravel是值得phper掌握的优雅框架。这里我们的实际代码量相对较小。
二、登陆/退出接口
微信登陆我们使用overtrue大神封装的composer包:overtrue/laravel-wechat
2.1 路由
在 routes/api.php
文件中添加路由:
Route::group(['prefix' => 'auth', 'namespace' => 'Auth'], function () {
Route::post('login', 'LoginController@login')->name('login');
Route::post('logout', 'LoginController@logout')->name('logout');
});
2.2 控制器
重写 App\Http\Controllers\Auth\LoginController
文件的login方法,使用 overtrue/laravel-wechat 包
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function login(Request $request)
{
$miniProgram = \EasyWeChat::miniProgram(); // 小程序
$sessionInfo = $miniProgram->auth->session($request->input('code'));
$decryptedData = $miniProgram->encryptor->decryptData($sessionInfo['session_key'], $request->input('iv'), $request->input('data'));
$user = User::firstOrCreate([
'openid' => $decryptedData['openId'],
],[
'name' => $decryptedData['nickName'],
'avatar' => $decryptedData['avatarUrl'],
'gender' => $decryptedData['gender'],
'unionid' => $decryptedData['unionId'],
'country' => $decryptedData['country'],
'province' => $decryptedData['province'],
'city' => $decryptedData['city'],
]);
$user->api_token = Str::random(80);
$user->save();
return response()->json(['token' => $user->api_token]);
}
}
退出接口没有进行重写,logout接口实际调用的是sessionGuard的退出逻辑,实际在小程序中也没有提供退出功能,大家知道就好。
三、视频解析、解析记录接口
这边就不拆开细讲了,整段代码贴出来,详细请看注释。
3.1 路由
在 routes/api.php
文件中添加路由:
代码如下(示例):
// 以下接口需要识别用户登陆态,因此添加api认证中间件
Route::group(['middleware' => 'auth:api'], function () {
// 视频解析接口
Route::post('video-parse', 'VideoParseController@parse')->name('video.parse');
// 当前用户解析记录总数
Route::get('records/total', 'RecordController@getTotalNum');
// 当前用户解析记录列表接口
Route::resource('records', 'RecordController');
});
3.2 控制器
3.2.1 视频地址解析
我们新建一个视频地址解析controller:
class VideoParseController extends Controller
{
public function parse(Request $request)
{
// 参数验证器
$request->validate([
'url' => 'required|string|url', //url参数格式验证
]);
$user = $request->user();
$url = $request->input('url');
Log::info("video-parse|user_id:{$user->id}|{$url}");
$urlInfo = parse_url($url);
$host = $urlInfo['host'];
$domain = implode('.', array_slice(explode('.', $host), -2));
// 优先尝试从缓存获取数据(缓存有效期3600秒)
[$noWatermarkUrl, $imageUrl] = Cache::remember(md5($url), 3600, function () use($domain, $url) {
// 根据域名判断短视频来源
switch ($domain) {
//抖音
case 'douyin.com':
$data = VideoManager::DouYin()->start($url);
break;
//微视
case 'qq.com':
$data = VideoManager::WeiShi()->start($url);
break;
//快手
case 'kuaishou.com':
case 'chenzhongtech.com':
$data = VideoManager::KuaiShou()->start($url);
break;
//最右
case 'izuiyou.com':
$data = VideoManager::ZuiYou()->start($url);
break;
//皮皮虾
case 'hulushequ.com':
case 'pipix.com':
$data = VideoManager::PiPiXia()->start($url);
break;
//皮皮搞笑
case 'ippzone.com':
$data = VideoManager::PiPiGaoXiao()->start($url);
break;
default:
abort(Response::HTTP_BAD_REQUEST, '解析失败,请检查地址');
}
// 视频地址
$videoUrl = Arr::get($data, 'video_url');
// 缩略图地址
$imageUrl = Arr::get($data, 'img_url');
// 视频地址为空时直接返回500状态码
abort_if(empty($videoUrl), Response::HTTP_INTERNAL_SERVER_ERROR, '解析失败,请稍后再试');
return [preg_replace('/^http:/', 'https:', $videoUrl), $imageUrl];
});
// 当得到无水印地址后,存入数据库,用于查阅解析历史
if ($noWatermarkUrl) {
$record = Record::firstOrNew(['url' => $url], [
'host' => $host,
]);
$record->no_water_mark_url = $noWatermarkUrl;
$record->image_url = $imageUrl;
$user->records()->save($record);
return response()->json([
'url' => $noWatermarkUrl,
'image' => $imageUrl,
'preview' => config('app.preview'), // 这里注意,这个参数是用来控制视频是否展示的!由于微信小程序个人主体不能涉及视频,所以需要服务端控制是否展示,需要审核通过后再显示视频,以达到目的!
]);
} else {
Cache::forget(md5($url));
return response()->json(['message' => '转换失败,请检查链接是否有效,或联系客服'], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
}
这里注意,返回参数中有一个preview参数,这个参数是用来控制视频是否展示的!由于微信小程序个人主体不能涉及视频,所以我们耍个小聪明,通过服务端控制视频是否展示,这样我们在小程序审核通过后再显示视频,以达到目的!(请勿滥用)
3.2.2 解析记录controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class RecordController extends Controller
{
// 获取某用户历史解析列表
public function index(Request $request)
{
$data = $request->user()->records()->orderBy('updated_at', 'desc')->paginate($request->input('size', 10))->toArray();
$data['preview'] = config('app.preview');
return response()->json($data);
}
// 获取某用户解析总数
public function getTotalNum(Request $request)
{
$totalNum = $request->user()->records()->count();
return response()->json([
'total_num' => $totalNum,
]);
}
// 删除某条记录
public function destroy($id, Request $request)
{
$result = $request->user()->records()->where('id', $id)->delete();
if ($result) {
return response()->json([
'message' => '删除成功'
]);
} else {
return response()->json([
'message' => '删除失败'
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
}
三、nginx代理下载配置
小程序下载域名有限制,转换的地址无法直接使用,需要在你的nginx配置中加入一条规则,对/download路径的请求,反代到源url中,配置如下,不做过多解释
# 根据url参数回源视频资源
resolver 8.8.8.8; #必须
location ~/download {
if ($query_string ~* ^(.*)url=(.*)$){
set $url $2;
proxy_pass $url;
}
}
总结
得益于我们核心代码使用了开源项目,我们只做了针对具体业务的封装,所以整体编码量相对较小,后续只需共同维护解析部分即可,这便是开源的力量,再次鸣谢: