| <?php |
|
|
| namespace App\Http\Controllers; |
|
|
| use App\Models\Video; |
| use App\Services\VideoImporter; |
| use App\Services\HLS\HLSConverter; |
| use Illuminate\Http\Request; |
| use Illuminate\Support\Facades\Storage; |
| use Symfony\Component\HttpFoundation\BinaryFileResponse; |
|
|
| class VideoController extends Controller |
| { |
| protected $importer; |
| protected $hlsConverter; |
|
|
| public function __construct(VideoImporter $importer, HLSConverter $hlsConverter) |
| { |
| $this->importer = $importer; |
| $this->hlsConverter = $hlsConverter; |
| } |
|
|
| |
| public function import(Request $request) |
| { |
| $this->validate($request, [ |
| 'import_link' => 'required|url', |
| 'import_title' => 'nullable|string|max:150', |
| 'enable_hls' => 'nullable|boolean', |
| 'hls_quality' => 'nullable|array|min:1|max:3', |
| 'hls_quality.*' => 'in:1080,720,480' |
| ]); |
|
|
| try { |
| $result = $this->importer->import( |
| $request->input('import_link'), |
| $request->input('import_title', ''), |
| (bool) $request->input('enable_hls', false), |
| $request->input('hls_quality', ['720']) |
| ); |
|
|
| return response()->json([ |
| 'status' => 'success', |
| 'data' => $result |
| ]); |
| } catch (\Exception $e) { |
| return response()->json([ |
| 'status' => 'error', |
| 'message' => $e->getMessage() |
| ], 500); |
| } |
| } |
|
|
| |
| public function streamHls($folder, $file = 'master.m3u8') |
| { |
| $path = public_path("hls/{$folder}/{$file}"); |
|
|
| if (!file_exists($path)) { |
| return response()->json(['error' => 'File not found'], 404); |
| } |
|
|
| $ext = pathinfo($path, PATHINFO_EXTENSION); |
|
|
| |
| if ($ext === 'm3u8') { |
| $content = file_get_contents($path); |
| $baseUrl = url("/api/hls/{$folder}"); |
|
|
| |
| $content = preg_replace( |
| '/(^\s*)(?!#)([\w\-\.%]+\.(ts|chunk|m4s))/m', |
| "$1{$baseUrl}/$2", |
| $content |
| ); |
|
|
| return response($content, 200, [ |
| 'Content-Type' => 'application/vnd.apple.mpegurl', |
| 'Access-Control-Allow-Origin' => '*', |
| 'Access-Control-Allow-Methods' => 'GET, OPTIONS', |
| 'Access-Control-Allow-Headers' => 'Range', |
| 'Cache-Control' => 'no-cache', |
| ]); |
| } |
|
|
| |
| $mime = in_array($ext, ['ts', 'chunk']) ? 'video/mp2t' : 'video/mp4'; |
|
|
| $response = new BinaryFileResponse($path); |
| $response->headers->set('Content-Type', $mime); |
| $response->headers->set('Access-Control-Allow-Origin', '*'); |
| $response->headers->set('Accept-Ranges', 'bytes'); |
| $response->headers->set('Cache-Control', 'no-cache'); |
|
|
| return $response; |
| } |
|
|
| |
| public function index(Request $request) |
| { |
| $perPage = $request->input('per_page', 15); |
| $videos = Video::orderBy('created_at', 'desc')->paginate($perPage); |
|
|
| return response()->json($videos); |
| } |
|
|
| public function show($id) |
| { |
| $video = Video::findOrFail($id); |
| return response()->json($video); |
| } |
|
|
| |
| public function destroy($id) |
| { |
| $video = Video::findOrFail($id); |
|
|
| |
| if ($video->path && file_exists($video->path)) { |
| @unlink($video->path); |
| } |
|
|
| |
| if ($video->thumbnail && file_exists(storage_path('app/' . $video->thumbnail))) { |
| @unlink(storage_path('app/' . $video->thumbnail)); |
| } |
|
|
| |
| if ($video->hls_enabled && $video->hls_master_playlist) { |
| $this->hlsConverter->deleteHLSFiles($video->hls_master_playlist); |
| } |
|
|
| $video->delete(); |
|
|
| return response()->json([ |
| 'status' => 'success', |
| 'message' => 'Đã xóa video thành công' |
| ]); |
| } |
| } |
|
|