Integrating video in Sanity using Mux Input and Vime/Youtube plugins

9 replies
Last updated: Nov 28, 2022
Hey everyone! Whats the best way to integrate video? It seems the
mux-studio-plugin
has a lot of bugs currently (causes the studio to crash/I am unable to delete videos).. Perhaps its easiest to just have a field pointing to a URL and then pass that within a
video
tag?
fields: [
 {
   name: 'vimeoUrl',
   title: 'Vimeo Video URL',
   type: 'url'
 }
]
AI Update

I understand the frustration with the Mux plugin issues! You have several good options for handling video in Sanity, and your URL approach is actually a solid, pragmatic solution.

Your URL approach is perfectly valid and often the simplest route. Here's how you can enhance it:

{
  name: 'video',
  title: 'Video',
  type: 'object',
  fields: [
    {
      name: 'url',
      title: 'Video URL',
      type: 'url',
      description: 'Vimeo, YouTube, or direct video URL'
    },
    {
      name: 'provider',
      title: 'Video Provider',
      type: 'string',
      options: {
        list: ['vimeo', 'youtube', 'direct']
      }
    },
    {
      name: 'thumbnail',
      title: 'Thumbnail',
      type: 'image',
      description: 'Optional custom thumbnail'
    }
  ]
}

Other alternatives to consider:

  1. Native file uploads: You can use Sanity's built-in file type to upload video files directly to Sanity's asset CDN. This works well for smaller videos but lacks the optimization and streaming features that specialized video platforms provide.
{
  name: 'video',
  title: 'Video File',
  type: 'file',
  options: {
    accept: 'video/*'
  }
}
  1. Cloudinary plugin: There's a sanity-plugin-cloudinary available that supports video uploads with transcoding and optimization capabilities.

  2. Wait for Mux plugin updates: If you specifically need Mux's features (adaptive streaming, analytics, etc.), you might check the plugin's GitHub repository for recent issues and updates. Sometimes these issues get resolved quickly.

My recommendation: If you're experiencing crashes with the Mux plugin, the URL approach you outlined is a great pragmatic solution. It's simple, reliable, and gives you full control. You can always migrate to a more integrated solution later when the plugin stabilizes or your needs change. Vimeo and YouTube handle all the transcoding and streaming optimization for you, so you're not losing much functionality compared to a full integration—especially if you're just embedding videos rather than building a complex video platform.

That is one possible way! But I will note that the Mux Input plugin got some love this week to address some of the issues it's had. The most recent version should perform better.
Hi, I’m using Vime for videos (YouTube, Vimeo or manually uploaded mp4 file).
Here’s the schema of the object:

import { TbBrandVimeo } from "react-icons/tb";
import React from 'react';
import getVideoId from 'get-video-id'
import { Vimeo, Player } from '@vime/react';

const VimeoPreview = ({value}) => {
  const { url } = value;
  const id = getVideoId(typeof url === 'string' ? url : '')?.id;
  if (!value || !url || !id){
    return <div>Vimeo Video (double click to add URL)</div>
  }
  return (
    <div id="vimeo-container">
      <Player controls>
        <Vimeo videoId={id} />
      </Player>
    </div>
  );
}

export default {
  name: 'vimeo',
  title: 'Vimeo',
  type: 'object',
  icon: TbBrandVimeo,
  fields: [
    {
      name: 'url',
      type: 'url',
      title: 'Vimeo video URL'
    }
  ],
  preview: {
  	select: {
  		url: 'url'
  	},
  	component: VimeoPreview
  }
}
You need to install:

@vime/core
@vime/react
get-video-id
For YouTube just replace “Vimeo” with “Youtube”
user M
Okay thank you for letting me know.. I will upgrade and check it out.
user S
that example really helps me out thank you for posting that 💯
Hei, just wondering how do you show video to the page from PortableText, just not working from my side
const components = {
  types: {
    image: ({ value }: { value: ImageWithAlt }) => {
      return (
        <Image src={value} width={400} quality={1} style={{ borderRadius: 12 }} height={225} />
      );
    },
  },
  video: ({ node }: MediaProps) => {
    const { url } = node;
    const id = getYouTubeId(url);
    console.log('get youtube id -> ', id)

    return (
      <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
        <p> video rendered here</p>
        <YouTube videoId={id ?? undefined} opts={youtubeOptions} />
      </div>
    );
  },
};

function PortableText({ value }: PortableTextProps) {
  console.log('value -> ', value)
  return <OriginalPortableText value={value} components={components} />;
}

export default PortableText;
const components = {

types: {

image: ({ value }: { value: ImageWithAlt }) => {

return (

<Image src={value} width={400} quality={1} style={{ borderRadius: 12 }} height={225} />

);

},

},

video: ({ node }: MediaProps) => {

const { url } = node;

const id = getYouTubeId(url);

console.log('get youtube id -> ', id)


return (

<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>

<p> video rendered here</p>

<YouTube videoId={id ?? undefined} opts={youtubeOptions} />

</div>

);

},

};


function PortableText({ value }: PortableTextProps) {

console.log('value -> ', value)

return <OriginalPortableText value={value} components={components} />;

}

export default PortableText;
user S
user S
does that still work for you with the v3? I don't see any preview with that code 🤔
Works fine for me. If you manually paste a random youtube iframe embed code instead of the video-container code from above, does that show for you in the preview?
user S
neither a Youtube URL nor a Youtube iframe actually, nothing shows up haha

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?