Embedding a video from the server

Hi and hello,

is it possible, to embedd a videofile which is stored on the server kirby is running on? Or does kirby only embedd youtube and vimeo videos (via the video-tag)??

Thank you,
Roland.

You can totally do this but you have make your own kirby tag for it, or populate it from a files field. I can share some code I use with Kirby 2 which should work with Kirby 3 with some minor adjustments.

Not tested it but something like this should do it…

The tag…

Kirby::plugin('roland/videotag', [
  'tags' => [
    'video' => [
      'attr' => [
        'width',
        'height',
        'poster',
        'text',
        'caption',
        'title',
        'class',
        'vidclass',
        'caption',
        'preload',
        'controls',
        'webm',
        'ogv',
        'mp4'
      ],
      'html' => function($tag) {
        $url     = $tag->attr('video');
        $caption = $tag->attr('caption');
        $alt     = $tag->attr('alt');
        $title   = $tag->attr('title');
        $link    = $tag->attr('link');
        $caption = $tag->attr('caption');
        $file    = $tag->file($url);

        // use the file url if available and otherwise the given url
        $url = $file ? $file  : url($url);
        // alt is just an alternative for text
        if($text = $tag->attr('text')) $alt = $text;
        // try to get the title from the image object and use it as alt text
        if($file) {
          if(empty($alt) and $file->alt() != '') {
            $alt = $file->alt();
          }
          if(empty($title) and $file->title() != '') {
            $title = $file->title();
          }
        }
        if(empty($alt)) $alt = pathinfo($url, PATHINFO_FILENAME);
        $args = array(
          'videos' => array( $file ),
          'width'  => $tag->attr('width'),
          'height' => $tag->attr('height'),
          'class'  => $tag->attr('vidclass'),
          'poster' => $tag->attr('poster'),
          'preload' => $tag->attr('preload'),
          'caption' => html($caption),
          'controls' => $tag->attr('controls'),
          'title'  => html($title),
          'url'    => html($url),
          'alt'    => html($alt));
        if ( $poster = $tag->page()->images()->find($tag->attr('poster'))) {
          $args['poster'] = $poster;
        }

        if ( $mp4 = $tag->page()->videos()->find($tag->attr('mp4'))) {
          $args['videos'][] = $mp4;
        }

        $video = snippet('common/site-video', $args, true);

        $figure = new Brick('figure');
        $figure->addClass($tag->attr('class'));
        $figure->append($video);
        if(!empty($caption)) {
          $figure->append('<figcaption>' . html($caption) . '</figcaption>');
        }
        return $figure;
      }
    ]
  ]
]);

This tag calls a snippet to render the HTML for actual player…

<?php

// stop without videos

if(empty($videos)) return;
// set some defaults
if(!isset($width))    $width    = 400;
if(!isset($height))   $height   = 300;
if(!isset($preload))  $preload  = true;
if(!isset($controls)) $controls = true;
// build the html atts for the video element
$preload  = ($preload)  ? ' preload="preload"'   : '';
$controls = ($controls) ? ' controls="controls"' : '';
$poster_attr = ($poster) ? ' poster="'. $poster->url() .'"' : '';
?>
<video width="<?= $width ?>" height="<?= $height ?>" class="<?= $class ?>" <?= $preload . $controls . $poster_attr ?>>

    <?php foreach($videos as $video): ?>
    <?php if(is_a($video, 'file')): ?>
    <source src="<?= $video->url() ?>" type="<?= $video->mime() ?>" />
    <?php endif ?>

    <?php if($poster):?>
      <a href="<?= $video->url() ?>"> <img src="<?= $poster->url() ?>" alt="<?= $title ?>" /> </a>
    <?php endif ?>

  <?php endforeach ?>

  <?php foreach($videos as $video): ?>
  <script type="application/ld+json">
  {
    "@context": "http://schema.org",
    "@type": "VideoObject",
    "name": "<?= $title ?>",
    "description": "<?= $caption ?>",
    "thumbnailUrl": "<?= $poster->url() ?>",
    "contentUrl": "<?= $video->url() ?>",
    "uploadDate": "<?= $video->modified('%d/%m/%Y', 'strftime') ?>"
  }
  </script>
  <?php endforeach ?>
</video>

And to use it in a textarea…

(video:videofile.mp4 width:100% height:100% poster:yourposterimage.jpg class:video-post title:Your Video Title caption:Your Video Caption)
1 Like

How to you want to integrate the video? Into a text field, then a (custom) KirbyTag as suggested by @jimbobrjames makes sense.

If you just want to add it in a template, you can use a standard HTML5 video tag (maybe in conjunction with a player). You can then fetch the file like any file directly from the page files, or from a select field.

Thank you for your replies.

@texnixe: My usecase is the following: I upload videos to the directories in the content-directory on the server, for example for blog-entries or, in my case, for special unpublished websites for my clients (i am a videoeditor and motion designer). Then i want to edit my text in the textfield, and there i want to embedd the video, (like this: (video: example.mp4 width: 480))

I will try, how the solution by @jimbobrjames works. Sounds good.

Thank you,
Roland.

So, i inserted the code by @jimbobrjames into my site. But it doesn`t work. But: i am not a programmer, or a kirby-crack. it can really be, that i made a lot of mistakes while copying the code:

Maybe you can help once again:

  • i copied the first block into the file /plugins/roland/index.php
  • then i copied the second block into the file /snippets/common/site-video.php
  • then i tried to insert this string into my textfield in the backend: “(video:comp-1.mp4 width:100% height:100% poster:bild.jpg class:video-post title:Your Video Title caption:Your Video Caption)”

when i now open the site, the debugger reacts:

Can you see, what went wrong? My skills are at the end at his point.

Ok, give me a few minutes and ill get it to work and post the code, i’ve been meaning to port it over to Kirby 3 anyway.

I think its not seeing the image and video files to get their URLs.

Ok @roland Here you go. Sorry that took a while, it needed more jiggling then expected…

Heres the new tag code…

<?php

Kirby::plugin('roland/video', [
  'tags' => [
      'video' => [
        'attr' => [
          'width',
          'height',
          'poster',
          'text',
          'caption',
          'title',
          'class',
          'vidclass',
          'caption',
          'preload',
          'controls',
          'mp4'
        ],
        'html' => function($tag) {

          $url          = $tag->video;
          $caption      = $tag->caption;
          $alt          = $tag->alt;
          $title        = $tag->title;
          $link         = $tag->link;
          $caption      = $tag->caption;
          $file         = $tag->parent()->file($url);
          $poster       = $tag->parent()->file($tag->poster);

          // use the file url if available and otherwise the given url
          $url = $file ? $file : url($url);

          // alt is just an alternative for text
          if($text = $tag->text) $alt = $text;

          // try to get the title from the image object and use it as alt text
          if($file) {
            if(empty($alt) and $file->alt() != '') {
              $alt = $file->alt();
            }
            if(empty($title) and $file->title() != '') {
              $title = $file->title();
            }
          }

          if(empty($alt)) $alt = pathinfo($url, PATHINFO_FILENAME);

          $args = array(
            'videos'    => array($file),
            'width'     => $tag->width,
            'height'    => $tag->height,
            'class'     => $tag->vidclass,
            'poster'    => $tag->poster,
            'preload'   => $tag->preload,
            'caption'   => $caption,
            'controls'  => $tag->controls,
            'title'     => $title,
            'url'       => $url,
            'alt'       => $alt

          );


          if($mp4 = $tag->parent()->file($file)) {
            $args['videos'][] = $mp4;
          }

          if($poster = $tag->parent()->file($tag->poster)) {
            $args['poster'] = $poster;
          }

          $video = snippet('common/site-video', $args, true);

          $caption = Html::tag('figcaption', [$caption]);

          $video .= $caption;

          $figure = Html::tag('figure', [$video], ['class' => $tag->class]);


          return $figure;
        }
      ]
    ]
]);

New snippet code…

<?php
// stop without videos
if(empty($videos)) return;
// set some defaults
if(!isset($width))    $width    = 400;
if(!isset($height))   $height   = 300;
if(!isset($preload))  $preload  = true;
if(!isset($controls)) $controls = true;
// build the html atts for the video element
$preload  = ($preload)  ? ' preload="preload"'   : '';
$controls = ($controls) ? ' controls="controls"' : '';
$poster_attr = ($poster) ? ' poster="'. $poster->url() .'"' : '';
?>

<video width="<?= $width ?>" height="<?= $height ?>" class="<?= $class ?>" <?= $preload . $controls . $poster_attr ?>>
<?php foreach($videos as $video): ?>
<?php if($video):?>
  <source src="<?= $video->url() ?>" type="<?= $video->mime() ?>" />
<?php endif ?>
<?php if($poster):?>
  <a href="<?= $video->url() ?>"> <img src="<?= $poster->url() ?>" alt="<?= $title ?>" /> </a>
<?php endif ?>
<?php endforeach ?>
<?php foreach($videos as $video): ?>
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "VideoObject",
  "name": "<?= $title ?>",
  "description": "<?= $caption ?>",
  "thumbnailUrl": "<?= $poster->url() ?>",
  "contentUrl": "<?= $video->url() ?>",
  "uploadDate": "<?= $video->modified('%d/%m/%Y', 'strftime') ?>"
}
</script>
<?php endforeach ?>
</video>

No changes required to the kirby tag that goes in the textarea. I just tested it working in my own site…

2 Likes

Oh wow, you are crazy. It works. Thank you very very much for your help (and that i learned something about tags und plugins and snippets).

@roland My pleasure… have fun.

1 Like

I would like to add a video tag to a template and a video field to the respective blueprint. How do I set up the required select field you mentioned? Do the following codes work?

Blueprint:

sections:
      video:
        label: Video
        type: select
        options: videos

Template:

<?php if ($video = $data->video()->toFile()): ?>
  <section>
        <video>
          <source src="<?= $video->url() ?>" type="video/mp4">
        </video>
    </section>
<?php endif ?>

You select field needs a query:

sections:
  video:
    label: Video
    type: select
    options: query
    query: page.videos

Instead of the select field, you might want to consider a files field.

1 Like

Thank you. In my YML page blueprint, I edited:

  video:
    type: files
    layout: cards
    template: video

I also created a respective YML file blueprint:

title:  Video
accept: 
  mime: video/*

Uploading, I get an error message:

video.mp4
Die Datei ist größer als die post_max_size Einstellung in der php.ini

So, I created a php.ini in the root folder of the site:

post_max_size = 200M

Unfortunately, it does not work. What is wrong?

Also you can try the plugin we just tested on getkirby.com:

Related PR to get information usage:

1 Like

Is the error still the same? Check with phpinfo() if the ini file is actually picked up and the settings show up.

Also, is that on localhost or your remote server? If shared hosting, what are their limitations?

1 Like

At the moment, I develop the site on MAMP localhost. It seems the php.ini file is not picked up. Instead of “post_max_size 200M”, the phpinfo() shows:

post_max_size 8M

Then I’d change it directly in the main php.ini and you need to restart the server.

I set post_max_size = 0 in the php.ini of MAMP and restarted the server. phpinfo() still shows the same 8M. What else can I do?

I updated MAMP. Now, I can upload videos.