vaersaagod / muxmate
Mux 关于流媒体的内容,伙伴们!
Requires
- php: >=8.2
- craftcms/cms: ^5.2.0
- firebase/php-jwt: ^6.9
- muxinc/mux-php: ^3.0
Requires (Dev)
- craftcms/ecs: dev-main
- craftcms/phpstan: dev-main
README
Mux 关于流媒体的内容,伙伴们!
描述
MuxMate 将 Mux 集成到 Craft CMS 中。
要求
此插件需要 Craft CMS 5.2.0 或更高版本,以及 PHP 8.2 或更高版本。
免责声明
这是一个 私有插件,为 Værsågod 及其朋友制作。
入门指南
1. 创建 Mux 环境
在 https://www.mux.com 上注册一个 Mux 账户,并添加一个环境。为每个 Craft 环境创建单独的 Mux 环境是个不错的想法。
2. 创建 Mux 访问令牌
为适当的 Mux 环境创建一个 Mux 访问令牌。令牌只需要 "Mux 视频" 权限。
复制访问令牌 ID 和密钥。
3. 配置 MuxMate
在您的存储库中创建一个文件 config/_muxmate.php
,并添加 Mux 访问令牌 ID 和密钥
<?php use craft\helpers\App; return [ 'muxAccessTokenId' => App::env('MUX_ACCESS_TOKEN_ID'), 'muxSecretKey' => App::env('MUX_SECRET_KEY'), ];
...还有很多配置设置(见 下面 了解所有设置),但这两项是您绝对需要的。
4. 将 MuxMate webhook 端点添加到 Mux 环境
没有工作的 Mux webhook,您将难以进行操作,所以不要跳过此步骤!
在您的 Mux 账户中,转到设置 -> Webhooks,选择适当的环境,并使用此 URL 创建一个新的 webhook
https://your-site.com/muxmate/webhook
如果这是一个本地环境(或无法从外部访问),您可以使用 Ngrok 或类似工具创建一个公开可用的 Webhook 端点 URL。
5. 创建 MuxMate 字段并将其添加到卷
MuxMate 随附一个自定义的 "MuxMate" 字段类型。创建一个具有此字段类型的字段(名称或处理程序不重要),并将其添加到计划上传视频的任何卷的字段布局中。
6. 上传视频到 Craft,并等待它
当包含 MuxMate 字段(在其字段布局中)的视频在 Craft 中保存时,其 URL 会自动 POST 到 Mux 的 assets/create
端点。假设视频的 URL 是公开可用的,Mux 然后下载视频并为它创建一个 Mux 资产。
Mux 端的流程是完全异步的,但遵循预定的顺序
- 创建 Mux 资产,包含基本元数据
- 创建 HLS 流;当准备好时,Mux 资产状态将变为 "ready"。
- 创建静态渲染(即转译的 MP4 资产);当完成时,Mux 资产元数据将包含一个键
static_renditions
。
假设 MuxMate webhook URL 已添加到 Mux(并且是公开可用的),Craft 中的资产 Mux 元数据将自动更新上述每个步骤。
7. 在前端渲染 Mux 视频
要渲染在 Mux 中创建的视频,只需在资产上调用 getMuxVideo()
方法以渲染一个自定义的 <mux-video>
网络组件实例
{{ video.getMuxVideo()|attr({ controls: true }) }}
本地测试
在本地环境中,Mux 通常无法访问您的视频。为确保它可以,请执行以下操作之一
使用云存储(S3、DO Spaces)文件系统来存储您的视频资产
一个简单的解决方案是使用某种云存储文件系统来存储视频的卷。您甚至可以设置一个仅本地使用的云存储文件系统,通过使用环境变量来设置卷的“资产文件系统”设置。
在本地环境中使用远程隧道覆盖卷的文件系统基本URL
如果您已经为webhook设置了类似Ngrok隧道,您也可以使用相同的隧道来确保Mux可以访问您的视频资产。这里有一些方法可以做到这一点
使用MuxMate覆盖文件系统的Base URL
您可以通过使用MuxMate的volumes
配置设置来配置MuxMate以覆盖特定卷中资产的Base URL。
假设您的视频存储在名为videos
的卷中(该卷使用的是Base URL设置为@web/uploads/videos
的文件系统),以下是您可以如何覆盖该Base URL的示例
在您的.env
文件中
VIDEO_VOLUME_BASE_URL=https://2d13-51-175-241-107.ngrok-free.app/uploads/videos
在您的config/_muxmate.php
文件中
<?php use craft\helpers\App; return [ 'muxAccessTokenId' => App::env('MUX_ACCESS_TOKEN_ID'), 'muxSecretKey' => App::env('MUX_SECRET_KEY'), 'volumes' => [ 'videos' => [ 'baseUrl' => App::env('VIDEO_VOLUME_BASE_URL'), ], ], ];
将文件系统的Base URL设置为自定义别名
另一个选项是添加一个自定义Yii别名,例如@videosBaseUrl
,并将您的卷的文件系统的“Base URL”设置为此别名(例如,@videosBaseUrl/uploads/videos
)。然后,使用Craft的aliases
配置设置来定义自定义的@videosBaseUrl
别名
在您的.env
文件中
VIDEOS_BASE_URL=https://2d13-51-175-241-107.ngrok-free.app
在您的config/general.php
文件中
'aliases' => [ '@videosBaseUrl' => App::env('VIDEOS_ALIAS') ?? App::env('PRIMARY_SITE_URL') ],
为现有的Craft视频资产创建(或更新)Mux资产
MuxMate资产在视频上传到Craft时创建,仅将MuxMate字段添加到卷中并不会对现有视频资产产生影响。如果您想MuxMate为现有Craft视频资产创建(或更新)Mux资产,有一些选项
重新保存资产(手动,通过控制面板)
MuxMate不会在Craft资产通过程序重新保存时创建或更新Mux资产(这是故意的)。但是,手动通过控制面板重新保存资产将会做到这一点。
在资产编辑页面点击“创建Mux资产”按钮。
与手动重新保存资产不同,这不会更新资产的dateUpdated
属性。
使用_muxmate/create
CLI命令
_muxmate/create
CLI命令可以用来创建Mux资产,无论是批量(即整个卷)还是单个资产
_muxmate/create
- 为所有视频资产创建Mux资产。通过传递--update=1
来重新创建任何现有Mux资产。
_muxmate/create --volume=videos
- 为卷videos
中的所有视频资产创建Mux资产。通过传递--update=1
来重新创建任何现有Mux资产。
_muxmate/create --assetId=1234
- 为ID为1234
的视频资产创建Mux资产。通过传递--update=1
来重新创建现有Mux资产。
视频的渲染和播放
Mux视频
渲染Mux视频最简单的方法是使用对所有资产都适用的getMuxVideo()
方法。
{{ video.getMuxVideo() }}
上述代码将渲染一个<mux-video>
网络组件,这是对原生<video>
元素的近似直接替换。<mux-video>
的好处是它自动填充HLS(如果用户的浏览器不支持),并且它自动与Mux Data集成。
设置<mux-video>
属性
可以使用|attr()
Twig过滤器来设置<mux-video>
组件的属性。
{{ video.getMuxVideo()|attr({ id: 'my-video', class: 'border-2 border-black', controls: true }) }}
内联视频(播放内联/循环视频)
要渲染内联视频(即视频循环),可以将参数inline: true
传递给getMuxVideo()
方法。
{{ video.getMuxVideo({ inline: true }) }}
以上自动为<mux-video>
组件设置以下属性
autoplay: 'muted',
loop: true,
muted: true,
playsinline: true,
disablePictureInPicture: true
或者,当然,您可以使用|attr()
Twig过滤器自己设置这些属性
{{ video.getMuxVideo()|attr({ autoplay: 'muted', loop: true, muted: true, playsinline: true, disablePictureInPicture: true }) }}
对象适配Mux视频
<mux-video>
的样式通常很简单。唯一例外是对象适配,因为需要将object-fit
应用于实际的<video>
元素——由于它在Web组件的shadow DOM中嵌套,因此无法访问。
默认情况下,Mux视频使用object-fit: contain
进行对象适配。要更改对象适配的值,可以使用以下CSS变量:
--media-object-fit
--media-object-position
使用object-fit: cover;
的示例
{{ video.getMuxVideo({ inline: true })|attr({ style: { '--media-object-fit': 'cover', '--media-object-position': '25% 10%' } }) }}
使用JS控制Mux视频播放
通常,<mux-video>
与原生的<video>
元素工作方式相同,即具有相同的方法(如.play()
、.pause()
等),并触发相同的事件(如timeupdate
等)。
然而,在尝试以编程方式与Mux视频交互之前,您应该确保自定义的<mux-video>
Web组件已加载,可以使用customElements
API
window.customElements.whenDefined('mux-video') .then(() => { const video = document.getElementById('video'); video.addEventListener('canplay', () => { video.play(); console.log('ready!'); }); }) .catch(error => { console.error(error); });
延迟加载<mux-video>
Web组件
<mux-video>
Web组件体积较大(约150K压缩后),因此延迟加载它可能是有意义的——即在<mux-video>
元素实际进入视口之前不加载它。
要自动在所有地方延迟加载<mux-video>
Web组件,只需将lazyloadMuxVideo
配置设置设置为true
<?php return [ 'lazyloadMuxVideo' => true, ];
实现自己的延迟加载策略
对于更复杂的使用情况,您可以通过将muxVideoUrl
配置设置设置为false
来防止MuxMate自动加载<mux-video>
Web组件。
<?php return [ 'muxVideoUrl' => false, ];
在此之后,您可以根据自己的喜好以任何延迟方式自行加载Web组件。例如
const video = document.getElementById('video'); let hasLoadedMuxVideoJs = false; const observer = new IntersectionObserver(([{ isIntersecting }]) => { if (isIntersecting && !hasLoadedMuxVideoJs) { const script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; script.src = 'https://cdn.jsdelivr.net.cn/npm/@mux/mux-video@0'; document.body.appendChild(script); } });
内容安全策略(CSP)
如果您正在实施CSP(好主意!),您可能需要将nonce设置为MuxMate创建的脚本标签。为此,请使用scriptSrcNonce
配置设置。以下是一个使用ToolMate插件创建nonce的示例
<?php use \vaersaagod\toolmate\ToolMate; return [ 'scriptSrcNonce' => ToolMate::getInstance()->csp->createNonce('script-src'), ];
此功能即使在启用模板缓存的情况下也能正常工作 🔥
从视频中获取图像和动画GIF
从视频中获取图像
getMuxImageUrl()
资产方法支持与Mux文档中描述的所有相同参数:https://docs.mux.com/guides/video/get-images-from-a-video。
示例
{% set imageUrl = video.getMuxImageUrl({ width: 1080, height: 720 }) %} <img src="{{ imageUrl }}" />
从视频中获取动画GIF
getMuxGifUrl()
资产方法支持与Mux文档中描述的所有相同参数:https://docs.mux.com/guides/video/get-images-from-a-video#get-an-animated-gif-from-a-video。
示例
{% set gifUrl = video.getMuxGifUrl({ start: 10, end: 20, width: 300, height: 150 }) %} <img src="{{ gifUrl }}" />
签名URL
为了保护您的Mux资产,对Mux URL进行签名可能是一个好主意。
创建签名密钥
要开始使用Mux签名URL,首先需要创建一个Mux签名密钥
- 在您的Mux账户中,转到设置 -> 签名密钥
- 选择适当的环境,然后单击“生成新密钥”
- 复制签名密钥ID和Base64编码的私钥(不要将其作为.pem文件下载)
- 配置MuxMate以使用签名密钥
<?php return [ ... 'muxSigningKey' => [ 'id' => App::env('MUX_SIGNING_KEY_ID'), 'privateKey' => App::env('MUX_SIGNING_PRIVATE_KEY'), ], ],
选择播放策略
MuxMate为您所有的资产创建公共和签名播放ID,因此使用签名ID只需选择正确的策略。
默认情况下,MuxMate使用所有资产的公共播放ID。要默认使用签名播放ID,配置MuxMate的defaultPolicy
配置设置
<?php return [ ... 'defaultPolicy' => 'signed', ];
创建视频流、静态版本URL或图像/GIF时,也可以通过传递参数signed
来选择特定的策略。
一些示例
签名Mux图像URL
{% set imageUrl = video.getMuxImageUrl({ width: 1080, height: 720 }, 'signed') %} <img src="{{ imageUrl }}" />
签名Mux GIF URL
{% set gifUrl = video.getMuxGifUrl({ start: 10, end: 20, width: 300, height: 150 }, 'signed') %} <img src="{{ gifUrl }}" />
签名<mux-video>
标签
{{ video.getMuxVideo({ inline: true }, null, 'signed') }}
查看Mux资产方法和属性,以获取支持signed
参数的方法的完整概述。
基于Mux数据查询资产
可以通过使用MuxMate字段的handle来执行基于Mux元数据的资产子查询,例如
{% set videos = entry.videos.muxMateFieldHandle({ status: 'ready' }).all() %}
此外,还支持:empty:
和:notempty:
指令,可以确保返回的资产在MuxMate字段中具有Mux数据
{% set videos = entry.videos.muxMateFieldHandle(':notempty:').all() %}
配置
MuxMate通过将文件config/_muxmate.php
添加到您的仓库中进行配置。
配置设置
muxAccessTokenId
[字符串|null]
默认: null
Mux访问令牌ID
muxSecretKey
[字符串|null]
默认: null
Mux访问令牌密钥
muxSigningKey
[数组|null]
默认 null
用于签名URL的签名密钥ID和私钥
'muxSigningKey' => [ 'id' => App::env('MUX_SIGNING_KEY_ID'), 'privateKey' => App::env('MUX_SIGNING_PRIVATE_KEY'), 'minExpirationTime' => 'PT5M', ],
defaultPolicy
[字符串|null]
默认 null
(默认为'public'
)
在生成Mux URL时使用的默认播放策略。应设置为'public'
(默认)或'signed'
。
defaultMp4Quality
[字符串|null]
默认 null
(默认为'high'
)
用于静态版本的默认质量。需要是'high'
(默认)、'medium'
或'low'
之一。
defaultMaxResolution
[字符串|null]
默认 null
用于HLS流的默认max_resolution
参数。需要是'720p'
、'1080p'
、'1440p'
或'2160p'
之一。
maxResolutionTier
[字符串|null]
默认 null
(默认为'1080p'
)
在创建新的Mux资产时使用的默认max_resolution_tier
参数。需要是'1080p'
、'1440p'
或'2160p'
之一。
muxVideoUrl
[字符串|bool|null]
默认: 'https://cdn.jsdelivr.net.cn/npm/@mux/mux-video@0'
<mux-video>
JS库的URL。如果要使用不同的分发,请将其设置为不同的URL(支持别名和环境变量),或者将其设置为false
以完全自行处理库的加载(例如,用于自定义延迟加载或其他类似用途)。
lazyloadMuxVideo
[bool]
默认: false
设置为true
以使MuxMate延迟加载<mux-video>
库。即,MuxMate不会在页面加载时自动加载(尽管是异步的),而是在<mux-video>
组件进入视口时创建IntersectionObserver并加载脚本。
scriptSrcNonce
[字符串|null]
默认 null
volumes
[数组|null]
默认: null
每卷配置设置。目前仅支持baseUrl
设置,请参阅上面的“在本地环境中覆盖您的卷文件系统Base URL”。
Mux资产方法和属性
MuxMate向资产模型添加了一些方法和属性
isMuxVideo()
[bool]
如果资产具有Mux资产ID,则返回true
。
isMuxVideoReady()
[bool]
如果资产具有Mux资产ID且具有“就绪”状态,即已准备好播放,则返回true
。
getMuxVideo(array|null options = null, array|null params = null, string|null policy = null)
[Markup|string]
@options
选项数组;inline
、lazyload
@params
Mux参数数组
@policy
'public'
或'signed'
之一
如果资产有Mux播放ID,则返回一个<mux-video>
网页组件。
options
数组可以包含以下设置
inline: true # Automatically sets all the required attributes for videos that should play inline. lazyload: true # Lazyloads the `<mux-video>` web component. Defaults to the `lazyloadMuxVideo` config setting
params
数组可以包含Mux视频参数(例如“播放修改器”),如max_resolution
参数
{{ asset.getMuxVideo(null, { max_resolution: '720p' }) }}
getMuxStreamUrl(array|null params = null, string|null policy = null)
[string|null]
@params
Mux参数数组
@policy
'public'
或'signed'
之一
如果资产有Mux播放ID,则返回HLS流URL。与getMuxVideo()
方法的@params
数组相同。
getMuxMp4Url(string|null quality = null, string|null policy = null)
[string|null]
@quality
可选值为'high'
、'medium'
、'low'
@policy
'public'
或'signed'
之一
如果资产有Mux播放ID和静态渲染版本,则返回MP4文件的URL。
如果quality
参数为null或设置为不可用的质量,则返回最高可用质量。
getMuxImageUrl(array|null params = null, string|null policy)
[string|null]
@params
数组为Mux参数,请参阅https://docs.mux.com/guides/video/get-images-from-a-video#thumbnail-query-string-parameters
@policy
'public'
或'signed'
之一
如果资产有Mux播放ID,则返回视频静态帧的URL。
getMuxGifUrl(array|null params = null, string|null policy)
[string|null]
@params array
参数数组,请参阅https://docs.mux.com/guides/video/get-images-from-a-video#animated-gif-query-string-parameters
@policy
'public'
或'signed'
之一
如果资产有Mux播放ID,则返回视频的动画GIF。
getMuxVideoDuration()
[float|null]
返回视频时长,单位为秒
getStaticRenditions()
[array|null]
返回视频可用静态渲染版本的数组。数组按质量('high'
、'medium'
和'low'
)索引。
getMuxAssetId()
[string|null]
返回Mux资产ID。
getMuxPlaybackId(string|null policy)
[string|null]
@policy
'public'
或'signed'
之一
返回给定策略的Mux播放ID。
getMuxData()
[array|null]
返回整个Mux资产元数据负载。请参阅https://docs.mux.com/api-reference#video/operation/get-asset
getMuxStatus()
[string|null]
返回Mux资产状态。如果显示为ready
,则表示可以继续。
getMuxAspectRatio()
[float|int|null]
返回视频的宽高比