@ados-agora/媒体
媒体图书馆 阿多尼斯·贾克,该部分 阿戈拉语Name 生态系统——生态系统
spa/lar-媒体-图书馆的感觉,上方 @adonisjs/drive。 。 。 .
将文件附加到实体,将它们组织到收藏中(MIME 白名单,单文件替换,
命令),生成图像转换(eager或懒惰)——加 内容变压器,同样的
图像外接: 捆绑 transformers.video() 用于 HLS/DASH 流媒体和
transformers.probe() 记录持续时间/编码c作为元数据,两者保持不变
record.conversions 地图。 存储完全委托给驱动器,所以您重新使用您的已有
local 编号 : s3 编号 : gcs 磁盘——这个软件包从不重新执行磁盘驱动程序.
这是 核心图书馆数字 : MediaLibrary, (中文(简体) ), AttachmentManager,则 MediaStore SPI(记忆中+)
卢西德,那个 ImageProcessor SPI (正), 缩写 Transformer SPI (HLS 视频包装+元数据)
探测器,捆绑 disks.s3() 驱动程序、代理/直接/可恢复的上传、可配置交付、
提供者 + defineConfig还有一个测试工具箱 管理层
装有控制台的船 - 登记 @adonis-agora/media/dashboard_provider 这都是消耗
应用程序需求(参见 盘子 ;没有单独的安装。 说对了
@adonis-agora/media-react
用于浏览器上传客户端.
子路径导出
软件包使用 子路径导出 (Agora idom),如此重的后端保持可选性:
| 子路径 | 什麽 |
|---|---|
@adonis-agora/media | 枪管- defineConfig, (中文(简体) ), stores, (中文(简体) ), processors, (中文(简体) ), disks, (中文(简体) ), uploadSessions, (中文(简体) ), MediaManager, (中文(简体) ), MediaLibrary, (中文(简体) ), AttachmentManager, (中文(简体) ), UploadManager, (中文(简体) ), ResumableUploadManager, (中文(简体) ), MediaDeliveryHandler, SPIs, 错误 |
@adonis-agora/media/services/main | 应用 MediaManager 单吨- import media from '@adonis-agora/media/services/main',随时可以导入(在首次使用时可以懒散解决) |
@adonis-agora/media/media_provider | 服务提供方(宾站) MediaManager,挂载可选上传/TUS路由) |
@adonis-agora/media/dashboard_provider | 嵌入式管理控制台提供者( React SPA + JSON API) |
@adonis-agora/media/dashboard | defineConfig + 类型 config/media_dashboard.ts, (中文(简体) ), DashboardService会场的助手们, ObjectInsightProvider |
@adonis-agora/media/configure | node ace configure 钩子 |
@adonis-agora/media/single-file | storeSingleFile 编号 : removeSingleFile 编号 : storeSingleFileWith 编号 : removeSingleFileWith 编号 : isSingleFileStoreAvailable ——让其他软件包代表单文件上传(如:相机)到媒体,而不依赖硬性 |
@adonis-agora/media/stores/lucid | 卢西德 MediaStore (单位:千美元)@adonisjs/lucid 端点) |
@adonis-agora/media/upload_sessions/lucid | 卢西德号可续航 UploadSessionStore (单位:千美元)@adonisjs/lucid 端点) |
@adonis-agora/media/disks/s3 | 捆绑 S3Disk (单位:千美元)@aws-sdk/client-s3 端点; 预签为手卷 SigV4 |
@adonis-agora/media/processors/sharp | 锋利 ImageProcessor (单位:千美元)sharp 端点) |
@adonis-agora/media/telescope | mediaTelescopeExtension (单位:千美元)@adonis-agora/telescope 可选对等点) |
@adonis-agora/media/testing | InMemoryMediaStore, (中文(简体) ), InMemoryDisk, (中文(简体) ), inMemoryDiskResolver, (中文(简体) ), FakeImageProcessor, (中文(简体) ), InMemoryUploadSessionStore |
@adonis-agora/media/types | 结构 Disk 编号 : DiskResolver 编号 : ExtendedDisk 编号 : MultipartUploadDisk 合同 |
安装
node ace add @adonisjs/drive # storage backend (required)
npm i @adonis-agora/media
node ace configure @adonis-agora/media
configure 注册媒体提供者 和仪表板供应商,发表 config/media.ts
财务报告和审定财务报表 config/media_dashboard.ts,并出版 两个 移徙—— media 表格 lucid
存储和会话表 lucid 上传会话商店. 删除不需要的
等同物不需要表格; 否则 node ace migration:run。管理控制台是
住在这里 /media/dashboard 当你的应用靴子 —— 看 盘子。 。 。 .
所需对等方 : @adonisjs/core (单位:千美元)^7.3.0和 @adonisjs/drive —— 说 无论是主要, (中文(简体) ), ^3.0.0 或者说
^4.0.0。 。 。 .
可选同伴, 仅在选中时懒惰地加载 :
@adonisjs/lucid(单位:千美元)^22.4.0()——lucidMediaStore编号 :UploadSessionStoresharp(单位:千美元)^0.33.0)——图像转换@aws-sdk/client-s3(单位:千美元)^3.0.0)——捆绑disks.s3()驱动程序( 已签名的 URL 是手卷 SigV4, 没有预签名包)@adonis-agora/telescope(单位:千美元)^0.4.0——望远镜监视器扩展
配置
// config/media.ts
import { defineConfig, stores, processors } from '@adonis-agora/media'
export default defineConfig({
// disk: 's3', // omit to use Drive's default disk
store: 'lucid',
stores: {
memory: stores.memory(),
lucid: stores.lucid({ connection: 'pg' }),
},
imageProcessor: processors.sharp(),
collections: [
{ name: 'avatar', single: true, acceptsMimeTypes: ['image/png', 'image/jpeg'] },
{
name: 'gallery',
conversions: [
{ name: 'thumb', width: 200, height: 200 },
{ name: 'og', width: 1200, eager: true },
],
},
],
})
使用
提供方绑定单通 MediaManager;通过服务导入(或) @inject() ) (中文(简体) ).
一个真正的上传控制器加载所有者,验证文件,并将其 tmp 字节流入一个
收藏库 :
// app/controllers/post_images_controller.ts
import { createReadStream } from 'node:fs'
import Post from '#models/post'
import media from '@adonis-agora/media/services/main'
import type { HttpContext } from '@adonisjs/core/http'
export default class PostImagesController {
async store({ request, response, params }: HttpContext) {
const post = await Post.findOrFail(params.id)
const image = request.file('image', { size: '5mb', extnames: ['jpg', 'png', 'webp'] })
if (!image) return response.badRequest({ error: 'An "image" file is required' })
const record = await media.library.attach({
ownerType: 'Post',
ownerId: post.id, // string | number — coerced for you
collection: 'gallery',
fileName: image.clientName,
mimeType: image.type!,
contents: createReadStream(image.tmpPath!), // Buffer | Readable
})
return response.created({ id: record.id, url: await media.library.url(record.id) })
}
}
阅读、列出和删除都经过同样的过程 media 单通 :
await media.library.url(record.id) // public url of the original
await media.library.url(record.id, 'thumb') // generated lazily on first call, then cached
await media.library.list('Post', post.id, 'gallery')
await media.library.delete(record.id)
// Or bind an owner once for a bulk upload
const gallery = media.library.for('Post', post.id)
await gallery.attach({ collection: 'gallery', fileName: image.clientName, mimeType: image.type!, contents })
// Column attachments (adonis-attachment style) — store the value object on a JSON column
const att = await media.attachments.createFromFile(
{ fileName: image.clientName, mimeType: image.type!, contents },
{ variants: [{ name: 'thumb', width: 100 }] },
)
user.avatarData = att.toJSON()
await media.attachments.url(att, 'thumb')
A 类 ConversionPreset 实值 { name, width?, height?, fit?, format?, quality?, eager? }。 Eager 预设为
同步生成 attach其它的都是懒散的 url(id, name) 财务报告和审定财务报表
被隐藏在记录. fit 财务报告和审定财务报表 format 地图直指尖端.
变形器和视频流
图像转换回答"相同的图像,大小不同". 变形器 回答其他问题:
将此内容转换为。变压器取出存储的媒体字节并生成许多
文件(一个视频包),一个文件(一个已提取的音频音轨),或者根本没有(一个元数据探测器)——
坚持不变 record.conversions 地图,所以预设和变压器共享一个命名空间
每个收藏.
带包裹的两艘飞船,都放在可选位置上 mediabunny 端点( 纯类型脚本 -) 无ffmpeg
二进制),在第一个输入的懒散 transform() 电话 :
// config/media.ts
import { defineConfig, transformers } from '@adonis-agora/media'
export default defineConfig({
collections: [
{
name: 'videos',
acceptsMimeTypes: ['video/mp4'],
transformers: [
transformers.video(), // CMAF segments + an HLS master + a DASH manifest
transformers.probe({ eager: true }), // duration / resolution / codecs, no artifact
],
},
],
})
变形被假定为很重,所以除非你标出,否则任何动静都不能运行 eager触发 1
从你的工作 - transform(id, name) 具有一能性,所以重试直接跳过:
await media.library.transform(mediaId, 'video')
transformers.video() 写入 CMAF 中标 默认的段, HLS 和 DASH 都播放, 所以一个副本
视频的两张名单. segments: 'ts' 为旧玩家撰写 MPEG- TS 上的 HLS,以及
engine: engines.ffmpeg({ ladder }) 用 ffmpeg 系统转码为 ABR 梯子。 服务于
软件包中有一个路由,可以授权每个显示和分区请求与
收藏库 access.read数字 :
router.get('/media/:id/stream/:conversion/*', media.access.streamRoute())
const video = await media.access.stream(ctx, mediaId) // manifest URLs for the player
与 delivery.signing,则整个软件包的URL签名,所以片段请求带有
授权随行,签名比视频有效。 写入自己的变压器是一个接口( Namename + 键 transform(context)(三);
上下文将记录交给你 原作的字节/流 和一个沙盒 write() 键
每个在转换前缀下的文物.
反应图像( E)next/image- 风格)
media.library.image(id) 返回全部为 <img> 需要作为简单的JSON: src页:1 srcSet 已建成
从收藏的同相图预设,内在 width编号 :height,模糊起来
placeholder 编辑 focalPoint把它变成 <MediaImage> 从
@adonis-agora/media-react这是一个 <img> 与懒惰的载荷, priority, (中文(简体) ), fill页:1
layout 计算 sizes,其后面的模糊预览直到装入为止.
// config/media.ts — presets at standard widths + the placeholder, from one flag
{ name: 'banner', responsive: true, stripMetadata: true }
// controller
return inertia.render('courses/show', { banner: await media.library.image(course.bannerMediaId) })
<MediaImage image={banner} alt={course.title} layout="constrained" priority />
更多图像侧:
- 联络点:
media.library.setFocalPoint(id, { x, y })使每个作物都保留这个部分object-fit: cover在浏览器中。 预设也要position: 'attention'。 。 。 . - 艺术方向 :
image(id, { conversions: [...] })返回组合,该组合<MediaPicture>在屏幕上互换. - 点播调整大小 : 运送路线
?w=640,调整一次并缓存为WebP(或AVIF,当你选择加入时),取决于Accept。只提供白色的宽度,除非 URL 签名. - 已签名的 URL : 与
delivery.signing, (中文(简体) ),media.library.deliveryUrl()财务报告和审定财务报表image()发送签名, 过期 URL, 而路由没有其他服务 . stripMetadata: true数字 : 从上传的原件中删除GPS,相机和时间戳.
授权( A)media.access(中文(简体) )
图书馆从不决定谁可以看文件,但它为你应用了你的规则. 你个
声明每个收藏中谁可以阅读和上传,并告知当前用户是谁(authkit,
@adonisjs/auth 或自用,或自用,或自用,或自用,或自用
import { authorizers } from '@adonis-agora/media'
import { authkitIdentity } from '@adonis-agora/media/authkit'
import { authz } from '@adonis-agora/media/authz'
defineConfig({
access: { identity: authkitIdentity() },
collections: [
{ name: 'avatar', access: { read: authorizers.owner(), write: authorizers.authenticated() } },
{ name: 'reports', access: { read: authz.can('reports.read') } },
],
})
const serveMedia = media.access.deliveryRoute() // build once, at route definition
router.get('/media/:id', serveMedia) // 401/403/404/400 handled
const banner = await media.access.image(ctx, id) // authorized descriptor
@adonis-agora/media/authkit 财务报告和审定财务报表 @adonis-agora/media/authz 仅在使用时装入他们的包.
两者都是可选的同龄人.
上传、S3和交付
大文件上传了三道花的飞船—— 代理服务器 (字节流出你的应用程序), 直接S3级
多块 (浏览器通过预先签名的部分URL直接上传到桶上),并 暂存
s 会话(可插入内存+ Lucid会话存储). 打开下面 uploads
内 config/media.ts; 供应商将路线挂起 /media/uploads 财务报告和审定财务报表 /media/uploads/tus。 。 。 .
export default defineConfig({
// ...
uploads: {
mode: 'auto', // 'direct' | 'proxy' | 'auto'
routes: { enabled: true },
resumable: { routes: { enabled: true } },
},
delivery: { mode: 'auto' }, // 'public' | 'signed' | 'proxy' | 'auto'
})
delivery 读侧对等器为 uploads.mode数字 : MediaLibrary.deliver(id, options?)
决心成立受歧视的工会—— { kind: 'redirect', url } 页:1 public编号 :signed,或
{ kind: 'stream', stream, mimeType, size, fileName } 页:1 proxy 所以,一个私人桶不需要
手卷出流道. MediaDeliveryHandler 财务报告和审定财务报表 TusUploadHandler 框架不可知性
路径将您的应用程序与它的中间软件相接; 既不执行授权 - 守卫
呼叫前的路径 handle。 。 。 .
同一送货路线根据需要调整大小(delivery.handle({ mediaId, width: qs.w, quality: qs.q, accept })) (中文(简体) ). 只有宽度 delivery.images.widths 除非请求被签名,否则
谈判 AVIF/WebP 来自 Accept与 delivery.signing (单位:千美元){ secret, expiresIn }),它只服务于
由 : media.library.deliveryUrl() 或者说 image(),直到他们过期.
捆绑起来 disks.s3() 驱动程序添加扩展操作(复制/移动/删除Mny/list/size/stat)和
本地多段, 相对于可选的 AWS SDK 端点 。 用浏览器驱动它
@adonis-agora/media-react。 。 。 .
盘子
一个管理控制台——浏览桶,监视正在更新的上传,上传对象,以及
复制/移动/取出横跨桶-船只 内嵌 在此包中:注册
@adonis-agora/media/dashboard_provider (自动由 node ace configure这一切都是一个
消费应用需求. 不单独安装软件包,不单独注册供应商.
// adonisrc.ts
providers: [
() => import('@adonis-agora/media/media_provider'),
() => import('@adonis-agora/media/dashboard_provider'),
]
// config/media_dashboard.ts
import { defineConfig } from '@adonis-agora/media/dashboard'
import { middleware } from '#start/kernel'
export default defineConfig({
basePath: '/media/dashboard', // where the SPA mounts (default)
actions: true, // enable copy/move/delete (default: false — read-only)
disks: ['s3', 'backups'], // browsable disks (default: derived from media config)
middleware: middleware.auth(), // gate the whole console — SPA + API
})
控制台读取/写出真实 @adonis-agora/media 表面( 磁盘)
list编号 :stat编号 :copy编号 :move编号 :deleteMany,可恢复的会话商店 MediaStore)——无
关于存储被重新执行。 完整配置引用、路径和文件夹操作语义
记录 @adonis-agora/media-dashboard, (中文(简体) ),
现在 构建时间源 用于控制台的 SPA 捆绑(安装时装在这里)和
仍可安装 独立 ——它自己的提供商是本作的瘦子代表,为主机保管
它已经直接注册。 不要在同一个应用程序中注册两个供应商.
诊断
所有九起生命周期事件—— attach, (中文(简体) ), delete, (中文(简体) ), conversion, (中文(简体) ), attachment.create, (中文(简体) ),
attachment.delete, (中文(简体) ), upload.start, (中文(简体) ), upload.progress, (中文(简体) ), upload.complete, (中文(简体) ), upload.abort - 已经
发射在 agora:media:* 通过 @agora/diagnostics:emit 全球时段——读取
结构,与 无硬依赖 打开 @adonis-agora/diagnostics当包裹不是时
已安装,排放是惰性不开放;当是时,望远镜通用监视器(或
@adonis-agora/media/telescope)自动捕捉出每个媒体事件.
测试
@adonis-agora/media/testing 用于 SPIs 的双相轮船, 这样您就可以练习库
没有磁盘、数据库或锐口:
import { MediaLibrary, StorageManager } from '@adonis-agora/media'
import { InMemoryMediaStore, inMemoryDiskResolver, FakeImageProcessor } from '@adonis-agora/media/testing'
const { resolve, disks } = inMemoryDiskResolver(['fs'])
const library = new MediaLibrary({
storage: new StorageManager({ default: 'fs', resolve }),
store: new InMemoryMediaStore(),
imageProcessor: new FakeImageProcessor(),
})
在真正的应用程序中,你也可以 drive.fake() 从 @adonisjs/drive 在磁盘后加内存
假的,同时保持其余的线条完好无损.
链接
- 重现 : https://github.com/Davide Carvalho/adonis-media 互联网档案馆的存檔,存档日期2013-12-02
- 更改日志 : https://github.com/Davide Carvalho/adonis-agora-media/blob/master/packages/adonis/CHANGELOG.md 互联网档案馆的存檔,存档日期2013-12-22
- 兄弟姐妹包 :
@adonis-agora/media-react, (中文(简体) ),@adonis-agora/media-dashboard
许可证
麻省理工学院