cms-orbit / video-field
A comprehensive video upload and multi-encoding system for CMS-Orbit with streaming support, transcoding, and thumbnails
1.0.0
2025-08-04 08:06 UTC
Requires
- php: ^8.3
- amuz/cms-orbit: ^3.0.21
- intervention/image: ^3.0
- league/flysystem: ^3.0
- symfony/process: ^7.0
Requires (Dev)
- orchestra/testbench: ^8.0
- phpunit/phpunit: ^10.0
README
CMS-Orbit 엔티티를 위한 고급 비디오 필드 시스템입니다. 다중 프로파일 인코딩, ABR 스트리밍, Orchid 관리자 패널 통합을 지원합니다.
🚀 주요 기능
- 다중 프로파일 인코딩: 240p ~ 4K 해상도 지원
- ABR 스트리밍: HLS/DASH 매니페스트 자동 생성
- Orchid 통합: 관리자 패널 필드 지원
- 비동기 처리: Queue 기반 Job 시스템
- 프로파일 폴백: 상위 해상도 요청 시 하위 해상도 제공
- 썸네일 생성: 자동 썸네일 및 스프라이트 생성
- Trait 기반: HasVideoField trait로 간편한 사용
📦 설치
1. Composer로 설치
composer require cms-orbit/video-field
2. 서비스 프로바이더 등록
config/app.php
에 서비스 프로바이더를 추가합니다:
'providers' => [ // ... CmsOrbit\VideoField\VideoServiceProvider::class, ],
3. 마이그레이션 실행
php artisan migrate
4. 설정 파일 발행 (선택사항)
php artisan vendor:publish --tag=video-field-config
🔧 설정
기본 설정
config/video.php
파일에서 다음 설정을 조정할 수 있습니다:
return [ 'storage' => [ 'disk' => env('MEDIA_DISK', 'public'), 'video_path' => env('VIDEO_STORAGE_PATH', 'videos/{videoId}'), 'thumbnails_path' => env('VIDEO_THUMBNAILS_PATH', 'videos/{videoId}/thumbnails'), 'sprites_path' => env('VIDEO_SPRITES_PATH', 'videos/{videoId}/sprites'), ], 'ffmpeg' => [ 'binary_path' => env('FFMPEG_BINARY_PATH', 'ffmpeg'), 'ffprobe_path' => env('FFPROBE_BINARY_PATH', 'ffprobe'), 'timeout' => env('FFMPEG_TIMEOUT', 3600), ], 'queue' => [ 'connection' => env('QUEUE_CONNECTION', 'redis'), 'queue_name' => env('VIDEO_QUEUE_NAME', 'encode_video'), 'max_tries' => env('VIDEO_MAX_TRIES', 3), 'retry_delay' => env('VIDEO_RETRY_DELAY', 300), ], ];
환경 변수
.env
파일에 다음 변수들을 설정하세요:
# Storage MEDIA_DISK=public VIDEO_STORAGE_PATH=videos/{videoId} VIDEO_THUMBNAILS_PATH=videos/{videoId}/thumbnails VIDEO_SPRITES_PATH=videos/{videoId}/sprites # FFmpeg FFMPEG_BINARY_PATH=/usr/bin/ffmpeg FFPROBE_BINARY_PATH=/usr/bin/ffprobe FFMPEG_TIMEOUT=3600 # Queue QUEUE_CONNECTION=redis VIDEO_QUEUE_NAME=encode_video VIDEO_MAX_TRIES=3 VIDEO_RETRY_DELAY=300 # Upload VIDEO_MAX_FILE_SIZE=5368709120 VIDEO_CHUNK_SIZE=1048576
📖 사용법
1. 모델에 HasVideoField Trait 추가
<?php namespace App\Models; use CmsOrbit\VideoField\Traits\HasVideoField; use CmsOrbit\VideoField\Entities\Video\Video; class Announcement extends DynamicModel { use HasVideoField; protected $videoFields = [ 'featured_video' => [ 'profiles' => ['HD@30fps', 'SD@30fps'], 'auto_thumbnail' => true, ], 'promo_video' => [ 'profiles' => ['FHD@30fps', 'HD@30fps'], 'auto_thumbnail' => true, ], ]; // 선택사항: 커스텀 프로파일 정의 protected function getVideoProfiles(): array { return [ 'FHD@30fps' => [ 'width' => 1920, 'height' => 1080, 'framerate' => 30, 'bitrate' => '8M' ], 'HD@30fps' => [ 'width' => 1280, 'height' => 720, 'framerate' => 30, 'bitrate' => '4M' ], ]; } }
2. Orchid Screen에서 VideoUpload 필드 사용
<?php namespace App\Orchid\Screens; use Orchid\Screen\Screen; use Orchid\Screen\Fields\Layout; use CmsOrbit\VideoField\Fields\VideoUpload\VideoUpload; class AnnouncementEditScreen extends Screen { public function layout(): array { return [ Layout::rows([ VideoUpload::make('featured_video') ->title('Featured Video') ->maxFileSize(2048) // 2GB ->chunkSize(1) // 1MB chunks ->autoProcess(true) ->showProgress(true) ->multiple(false) ->allowedExtensions(['mp4', 'mov', 'avi']) ->help('Upload a featured video for this announcement'), VideoUpload::make('promo_video') ->title('Promotional Video') ->maxFileSize(1024) // 1GB ->autoProcess(true) ->help('Upload a promotional video'), ]), ]; } }
3. 비디오 데이터 접근
$announcement = Announcement::find(1); // 비디오 객체 가져오기 $video = $announcement->getVideo('featured_video'); // 비디오 URL 가져오기 (프로파일 폴백 포함) $videoUrl = $video->getUrl('HD@30fps'); // HD 프로파일이 없으면 SD로 폴백 // ABR 스트리밍 URL $hlsUrl = $video->getHlsManifestUrl(); $dashUrl = $video->getDashManifestUrl(); // 플레이어 메타데이터 $playerData = $video->getPlayerMetadata();
4. 프론트엔드에서 비디오 플레이어 사용
<template> <div> <VideoPlayer :video="videoData" :autoplay="false" :controls="true" :width="640" :height="360" /> </div> </template> <script setup> import VideoPlayer from '@/packages/cms-orbit-video/resources/js/Components/VideoPlayer.vue' const props = defineProps({ videoData: { type: Object, required: true } }) </script>
🎯 기본 프로파일
패키지는 다음 기본 프로파일을 제공합니다:
프로파일 | 해상도 | 프레임레이트 | 비트레이트 | 용도 |
---|---|---|---|---|
4K@60fps | 3840x2160 | 60fps | 15M | 고화질 콘텐츠 |
4K@30fps | 3840x2160 | 30fps | 10M | 4K 콘텐츠 |
FHD@60fps | 1920x1080 | 60fps | 12M | 고프레임레이트 |
FHD@30fps | 1920x1080 | 30fps | 8M | 풀HD 콘텐츠 |
HD@30fps | 1280x720 | 30fps | 4M | HD 콘텐츠 |
SD@30fps | 640x480 | 30fps | 2M | 모바일 최적화 |
🔄 비동기 처리
Job 체인
비디오 업로드 시 다음 Job들이 순차적으로 실행됩니다:
- VideoEncodeJob: 다중 프로파일 인코딩
- VideoThumbnailJob: 썸네일 생성
- VideoSpriteJob: 스프라이트 시트 생성
- VideoManifestJob: ABR 매니페스트 생성
Queue 설정
# Queue 워커 시작 php artisan queue:work --queue=encode_video # 또는 Supervisor 사용 [program:video-encode] process_name=%(program_name)s_%(process_num)02d command=php /path/to/artisan queue:work --queue=encode_video --sleep=3 --tries=3 autostart=true autorestart=true user=www-data numprocs=2 redirect_stderr=true stdout_logfile=/path/to/worker.log
🧪 테스트
테스트 실행
# 모든 테스트 실행 php artisan test packages/cms-orbit-video/tests/ # 특정 테스트 실행 php artisan test packages/cms-orbit-video/tests/Unit/VideoModelTest.php
테스트 결과
- VideoModelTest: 8/8 통과 ✅
- AbrManifestServiceTest: 6/6 통과 ✅
- VideoJobsTest: 11/11 통과 ✅
- VideoIntegrationTest: 5/5 통과 ✅
총 30개 테스트 모두 통과! 🎉
📚 API 참조
Video 모델
// 비디오 URL 가져오기 (프로파일 폴백 포함) $video->getUrl(?string $profile = null): ?string // ABR 매니페스트 URL $video->getHlsManifestUrl(): ?string $video->getDashManifestUrl(): ?string // 플레이어 메타데이터 $video->getPlayerMetadata(): array // 사용 가능한 프로파일 $video->getAvailableProfiles(): array // ABR 지원 여부 $video->supportsAbr(): bool
HasVideoField Trait
// 비디오 객체 가져오기 $model->getVideo(string $field): ?Video // 비디오 URL 가져오기 $model->getVideoUrl(string $field, ?string $profile = null): ?string // 비디오 존재 여부 $model->hasVideo(string $field): bool // 비디오 첨부 $model->attachVideo(string $field, Video $video): void
🛠️ 명령어
콘솔 명령어
# 비디오 인코딩 php artisan video:encode {video_id} [--profile=] [--force] # 썸네일 생성 php artisan video:thumbnail {video_id} [--time=5] [--force] # 스프라이트 생성 php artisan video:sprite {video_id} [--frames=100] [--columns=10] [--rows=10] [--force] # 전체 프로세스 php artisan video:process-all {video_id} [--force]
🔧 문제 해결
일반적인 문제들
-
FFmpeg not found
# FFmpeg 설치 sudo apt-get install ffmpeg # 경로 확인 which ffmpeg which ffprobe
-
Queue Job 실패
# Queue 상태 확인 php artisan queue:failed # 실패한 Job 재시도 php artisan queue:retry all
-
권한 문제
# Storage 디렉토리 권한 설정 chmod -R 775 storage/app/public/videos chown -R www-data:www-data storage/app/public/videos
🤝 기여하기
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
📄 라이선스
이 프로젝트는 MIT 라이선스 하에 배포됩니다. 자세한 내용은 LICENSE 파일을 참조하세요.
🆘 지원
CMS-Orbit Video Field Package - 고급 비디오 필드 시스템으로 CMS-Orbit을 더욱 강력하게 만들어보세요! 🎬