add thumbnails to videos
This commit is contained in:
parent
822d9ba225
commit
2b648bd8e6
3 changed files with 26 additions and 10 deletions
|
|
@ -143,15 +143,15 @@ export default function Recorder({ closeModal, step, setStep }: Props) {
|
|||
}
|
||||
};
|
||||
|
||||
function generateThumbnail(video: HTMLVideoElement) {
|
||||
const generateThumbnail = async (video: HTMLVideoElement) => {
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = video.videoWidth;
|
||||
canvas.height = video.videoHeight;
|
||||
canvas
|
||||
.getContext("2d")
|
||||
?.drawImage(video, 0, 0, canvas.width, canvas.height);
|
||||
return canvas.toDataURL();
|
||||
}
|
||||
return await new Promise((resolve) => canvas.toBlob(resolve));
|
||||
};
|
||||
|
||||
const handleUpload = async () => {
|
||||
if (!blob || !videoRef.current) return;
|
||||
|
|
@ -169,11 +169,11 @@ export default function Recorder({ closeModal, step, setStep }: Props) {
|
|||
.put(signedVideoUrl, blob.slice(), {
|
||||
headers: { "Content-Type": "video/webm" },
|
||||
})
|
||||
.then(() => {
|
||||
.then(async () => {
|
||||
if (!videoRef.current) return;
|
||||
return axios.put(
|
||||
signedThumbnailUrl,
|
||||
generateThumbnail(videoRef.current),
|
||||
await generateThumbnail(videoRef.current),
|
||||
{
|
||||
headers: { "Content-Type": "image/png" },
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,11 +94,12 @@ const VideoList: NextPage = () => {
|
|||
) : (
|
||||
<div className="flex-start grid w-full max-w-[1300px] grid-cols-[repeat(auto-fill,250px)] flex-row flex-wrap items-center justify-center gap-14 px-4 pb-16">
|
||||
{videos &&
|
||||
videos.map(({ title, id, createdAt }) => (
|
||||
videos.map(({ title, id, createdAt, thumbnailUrl }) => (
|
||||
<VideoCard
|
||||
title={title}
|
||||
id={id}
|
||||
createdAt={createdAt}
|
||||
thumbnailUrl={thumbnailUrl}
|
||||
key={id}
|
||||
/>
|
||||
))}
|
||||
|
|
@ -122,6 +123,7 @@ const VideoList: NextPage = () => {
|
|||
interface VideoCardProps {
|
||||
title: string;
|
||||
id: string;
|
||||
thumbnailUrl: string;
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
|
|
@ -137,13 +139,13 @@ const VideoCardSkeleton = () => {
|
|||
);
|
||||
};
|
||||
|
||||
const VideoCard = ({ title, id, createdAt }: VideoCardProps) => {
|
||||
const VideoCard = ({ title, id, createdAt, thumbnailUrl }: VideoCardProps) => {
|
||||
return (
|
||||
<Link href={`/share/${id}`}>
|
||||
<div className="h-[240px] w-[250px] cursor-pointer overflow-hidden rounded-lg border border-[#6c668533] text-sm font-normal">
|
||||
<figure>
|
||||
<Image
|
||||
src="https://i3.ytimg.com/vi/BuaKzm7Kq9Q/maxresdefault.jpg"
|
||||
src={thumbnailUrl}
|
||||
alt="video thumbnail"
|
||||
width={248}
|
||||
height={139.5}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,21 @@ export const videoRouter = createTRPCRouter({
|
|||
},
|
||||
});
|
||||
|
||||
return videos;
|
||||
const videosWithThumbnailUrl = await Promise.all(
|
||||
videos.map(async (video) => {
|
||||
const thumbnailUrl = await getSignedUrl(
|
||||
ctx.s3,
|
||||
new GetObjectCommand({
|
||||
Bucket: env.AWS_BUCKET_NAME,
|
||||
Key: video.userId + "/" + video.id + "-thumbnail",
|
||||
})
|
||||
);
|
||||
|
||||
return { ...video, thumbnailUrl };
|
||||
})
|
||||
);
|
||||
|
||||
return videosWithThumbnailUrl;
|
||||
}),
|
||||
get: publicProcedure
|
||||
.input(z.object({ videoId: z.string() }))
|
||||
|
|
@ -95,7 +109,7 @@ export const videoRouter = createTRPCRouter({
|
|||
s3,
|
||||
new PutObjectCommand({
|
||||
Bucket: env.AWS_BUCKET_NAME,
|
||||
Key: video.userId + "/" + video.id + "thumbnail",
|
||||
Key: video.userId + "/" + video.id + "-thumbnail",
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue