Частное хранилище Laravel Videojs + vue.js

Я столкнулся с проблемой доступа к видео, хранящимся в частном порядке, с моего сервера через laravel, videojs и vuejs.

Вот мой метод контроллера:

 public function fetchPrivateVideo($video)
{

    $video_path = '/private/courses/episodes/' . $video . "/" . $video . '.m3u8';
    // $video_path = '/private/courses/episodes/' . $video . '.mp4';

    if (!Storage::disk('local')->exists($video_path)) {
        abort(404);
    } else {
        $local_path = config('filesystems.disks.local.root') . DIRECTORY_SEPARATOR . $video_path;

        return response()->file($local_path);
    }
}

Ответ от этих методов, например, таков:

EXTM3U

EXT-X-STREAM-INF:ПОЛОСА=100000

060204b9-a084-44bf-86f2-c1128dd6bcb9_100.m3u8

EXT-X-STREAM-INF:ПОЛОСА=250000

060204b9-a084-44bf-86f2-c1128dd6bcb9_250.m3u8

EXT-X-STREAM-INF:ПОЛОСА=500000

060204b9-a084-44bf-86f2-c1128dd6bcb9_500.m3u8

это тот же ответ общедоступных видео при доступе.

У меня есть простой проигрыватель videojs и пользовательский компонент vuejs:

    export default {
  props: ["episode", "course", "author"],
  data() {
    return {
      videoLoaded: true,
      videoOptions: {
        autoplay: false,
        controls: true,

        sources: [
          {
            src: `/video/episode/${this.episode.path}/fetch`,
            type: "application/x-mpegURL"
          }
        ]
      }
    };
  },
  components: {
    appComments,
    VideoPlayer
  }
};

Данные из вышеуказанных компонентов затем используются в общих компонентах видеоплеера, которые выглядят следующим образом:

   <template>
  <div>
    <video
      ref="videoPlayer"
      class="video-js vjs-big-play-centered"
      controls
      preload="auto"
      width="640"
      height="268"
      data-setup='{"fluid": true}'
    ></video>
  </div>
</template>

<script>
import videojs from "video.js";

export default {
  name: "VideoPlayer",
  props: {
    options: {
      type: Object,
      default() {
        return {};
      }
    }
  },
  data() {
    return {
      player: null
    };
  },
  mounted() {
    this.player = videojs(
      this.$refs.videoPlayer,
      this.options
      //   function onPlayerReady() {
      //     console.log("onPlayerReady", this);
      //   }
    );
  },
  beforeDestroy() {
    if (this.player) {
      this.player.dispose();
    }
  }
};
</script>
<style src="video.js/dist/video-js.min.css"></style>

Проблема в том, что видео не загружается и не запускается, оно просто создает много запросов, безуспешно пытающихся загрузить видео, и игроки остаются мертвыми на простом вращающемся загрузочном колесе.

Может ли кто-нибудь посоветовать мне, как справиться с этой проблемой? Мне нужно, чтобы некоторые видео были доступны в частном порядке после некоторых проверок, выполненных в промежуточном программном обеспечении. Обратите внимание, что это SPA, встроенный в laravel и vue.js.


person EUCDev    schedule 17.03.2020    source источник


Ответы (1)


Я узнал очень интересный факт. Мне пришлось изменить метод моего контроллера, потому что те многочисленные запросы, которые он создал, пытались получить следующую часть видео на основе файла списка воспроизведения m3u8, но не могли, потому что URL-адрес был неправильным, и файлы не были найдены. Обратите внимание, что URL-адрес меняется, но каждая следующая часть видео. Как это:

Начальная выборка видео: URL-адрес запроса: localhost:800/video/episode/fetch/060204b9-a084-44bf-86f2-c1128dd6bcb9

Следующие URL-адреса: URL-адрес запроса: localhost:800/video/episode/fetch/060204b9-a084-44bf-86f2-c1128dd6bcb9_500.m3u8

URL запроса: localhost:800/video/episode/fetch/060204b9-a084-44bf-86f2-c1128dd6bcb9_500_00000.ts

и т. д.

Вот как я отредактировал метод контроллера:

    public function fetchPrivateVideo($video)
{
    $arr = explode("_", $video, 2);
    $first = $arr[0];

    $contains = \Str::contains($video, ['.m3u8', 'ts']);

    if ($contains) {
        $video_path = '/private/courses/episodes/' . $first . "/" . $video;
    } else {
        $video_path = '/private/courses/episodes/' . $first . "/" . $video . '.m3u8';
    }

    if (!Storage::disk('local')->exists($video_path)) {
        abort(404);
    } else {
        $local_path = config('filesystems.disks.local.root') . DIRECTORY_SEPARATOR . $video_path;

        return response()->file($local_path);
}

В основном я изменяю путь, потому что после извлечения начальной части видео вам нужно изменить URL-адрес, чтобы он извлекал следующие части.

Также будьте очень внимательны при указании маршрута загрузки видео и следующих частей. Вам нужно что-то, что заканчивается параметрами и не имеет фиксированных слов между ними.

Неверно: Route::get('/video/episode/{video}/fetch', 'VideoController@fetchPrivateVideo');

Правильно: Route::get('/video/episode/fetch/{video}', 'VideoController@fetchPrivateVideo');

person EUCDev    schedule 17.03.2020
comment
Спасибо, что предоставили это. ваш код все еще работает? - person Pooria Honarmand; 08.07.2020