处理用户视频上传
在一个用户可以上传视频并编辑它们的应用中,我们可以通过在上传完成之前将视频加载到播放器中来提供更好的用户体验。好消息是:这可以很容易地实现!
允许用户上传
我们有一个组件,返回一个包含 URL 作为源的 <Video>
标签。
MyComposition.tsxtsx
import {AbsoluteFill ,Video } from "remotion";typeVideoProps = {videoURL : string;};export constMyComponent :React .FC <VideoProps > = ({videoURL }) => {return (<AbsoluteFill ><Video src ={videoURL } /></AbsoluteFill >);};
MyComposition.tsxtsx
import {AbsoluteFill ,Video } from "remotion";typeVideoProps = {videoURL : string;};export constMyComponent :React .FC <VideoProps > = ({videoURL }) => {return (<AbsoluteFill ><Video src ={videoURL } /></AbsoluteFill >);};
视频 URL 将从 Remotion Player 传递给我们的组件。
使用 <input type="file">
元素,我们允许用户上传。
一旦文件完全上传到云端,URL 将被设置,并且可以被组件用来显示视频。
App.tsxtsx
import {Player } from "@remotion/player";import {useState } from "react";export constRemotionPlayer :React .FC = () => {const [videoUrl ,setVideoUrl ] =useState <string | null>(null);consthandleChange =useCallback (async (event :React .ChangeEvent <HTMLInputElement >) => {if (event .target .files === null) {return;}constfile =event .target .files [0];//upload is an example function & returns a URL when a file is uploaded on the cloud.constcloudURL = awaitupload (file );// E.g., cloudURL = https://exampleBucketName.s3.ExampleAwsRegion.amazonaws.comsetVideoUrl (cloudURL );},[]);return (<div >{videoUrl === null ? null : (<Player component ={MyComposition }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}inputProps ={{videoUrl }}/>)}<input type ="file"onChange ={handleChange } /></div >);};
App.tsxtsx
import {Player } from "@remotion/player";import {useState } from "react";export constRemotionPlayer :React .FC = () => {const [videoUrl ,setVideoUrl ] =useState <string | null>(null);consthandleChange =useCallback (async (event :React .ChangeEvent <HTMLInputElement >) => {if (event .target .files === null) {return;}constfile =event .target .files [0];//upload is an example function & returns a URL when a file is uploaded on the cloud.constcloudURL = awaitupload (file );// E.g., cloudURL = https://exampleBucketName.s3.ExampleAwsRegion.amazonaws.comsetVideoUrl (cloudURL );},[]);return (<div >{videoUrl === null ? null : (<Player component ={MyComposition }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}inputProps ={{videoUrl }}/>)}<input type ="file"onChange ={handleChange } /></div >);};
upload()
函数的实现是特定于提供程序的,我们在本文中不展示实现。我们假设它是一个接受文件、上传文件并返回 URL 的函数。
乐观更新
当我们开始上传文件时,我们可以使用 URL.createObjectURL()
创建一个 Blob URL,该 URL 可用于在 <Video>
标签中显示本地文件。当文件上传完成并且我们获取到远程 URL 时,组件应使用远程 URL 作为源。
App.tsxtsx
import {Player } from "@remotion/player";import {useCallback ,useState } from "react";typeVideoState =| {type : "empty";}| {type : "blob" | "cloud";url : string;};export constRemotionPlayer :React .FC = () => {const [videoState ,setVideoState ] =useState <VideoState >({type : "empty",});consthandleChange =useCallback (async (event :React .ChangeEvent <HTMLInputElement >) => {if (event .target .files === null) {return;}constfile =event .target .files [0];constblobUrl =URL .createObjectURL (file );setVideoState ({type : "blob",url :blobUrl });constcloudUrl = awaitupload (file );setVideoState ({type : "cloud",url :cloudUrl });URL .revokeObjectURL (blobUrl );},[]);return (<div >{videoState .type !== "empty" ? (<Player component ={MyComposition }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}inputProps ={{videoUrl :videoState .url }}/>) : null}<input type ="file"onChange ={handleChange } /></div >);};
App.tsxtsx
import {Player } from "@remotion/player";import {useCallback ,useState } from "react";typeVideoState =| {type : "empty";}| {type : "blob" | "cloud";url : string;};export constRemotionPlayer :React .FC = () => {const [videoState ,setVideoState ] =useState <VideoState >({type : "empty",});consthandleChange =useCallback (async (event :React .ChangeEvent <HTMLInputElement >) => {if (event .target .files === null) {return;}constfile =event .target .files [0];constblobUrl =URL .createObjectURL (file );setVideoState ({type : "blob",url :blobUrl });constcloudUrl = awaitupload (file );setVideoState ({type : "cloud",url :cloudUrl });URL .revokeObjectURL (blobUrl );},[]);return (<div >{videoState .type !== "empty" ? (<Player component ={MyComposition }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}inputProps ={{videoUrl :videoState .url }}/>) : null}<input type ="file"onChange ={handleChange } /></div >);};
这将导致用户在将视频拖入输入字段时立即看到视频。在不再使用本地视频时,调用 URL.revokeObjectURL()
是一个良好的做法,以释放已使用的内存。