Как разделить видеофайл на небольшие фрагменты и загрузить на сервер?

Ссылка скопирована
1 ответ

Пешу пет-проект для саморазвития и столкнулся со следующей проблемой:
На сайте есть форма загрузки файлов. Все файлы разделяются на чанки и по очереди загружаются на сервер по api.
На первом чанке создаётся файл, а на последующих дополняется текст (из чанка) в конце файла.

Загружать фото/pdf в таком формате получается. А вот с архивами и видео (только эти форматы ещё проверил) не подходит. Архив вообще не открывается (даже ошибки нет), а видео максимум длится пару секунд (скорей всего это нормальный первый чанк созданный) и зависает.

PS: В идеале хочу в S3 хранилище загрузить. Но пока тестирую - загружаю локально.

Обработка чанков и их загрузка:

const uploadFile = async () => { 	let number_chunk = 1; 	let max_chunk = chunks.value.length;  	statusUpload.value = true;  	for (let chunk of chunks.value) { 		const upload = await uploadChunk(chunk, number_chunk, max_chunk);  		if (!upload) { 			console.log('Ошибка загрузки файла') 			break; 		}  		activeUploadChunk.value += 1; 		number_chunk += 1; 	}  	statusUpload.value = false; }

const uploadFile = async () => { let number_chunk = 1; let max_chunk = chunks.value.length; statusUpload.value = true; for (let chunk of chunks.value) { const upload = await uploadChunk(chunk, number_chunk, max_chunk); if (!upload) { console.log('Ошибка загрузки файла') break; } activeUploadChunk.value += 1; number_chunk += 1; } statusUpload.value = false; }

Загрузка файла:

const uploadChunk = async (chunk, number_chunk, max_chunk) => { 	let formData = new FormData(); 	formData.append('name', file.value.files[0].name) 	formData.append('type', file.value.files[0].type) 	formData.append('number_chunk', number_chunk) 	formData.append('max_chunk', max_chunk) 	formData.append('chunk', chunk);  	const {data, error} = await useAsyncData(() => client('/api/videos/upload', { 		method: 'post', 		body: formData, 	}));  	return error; }

const uploadChunk = async (chunk, number_chunk, max_chunk) => { let formData = new FormData(); formData.append('name', file.value.files[0].name) formData.append('type', file.value.files[0].type) formData.append('number_chunk', number_chunk) formData.append('max_chunk', max_chunk) formData.append('chunk', chunk); const {data, error} = await useAsyncData(() => client('/api/videos/upload', { method: 'post', body: formData, })); return error; }

Laravel метод загрузки:

public function upload(Request $request)     {         if ($request->hasFile('chunk')) {             $data = $request->all();             $chunk = $request->file('chunk');              // Имя файла             $fileName = $data['name'];             $exlodeName = explode('.', $fileName);             $fileExtension = $exlodeName[count($exlodeName) - 1];             $fileName = md5($fileName) . '.' . $fileExtension;              $storage = Storage::disk('public');              try {                 if ($data['number_chunk'] === 1) {                     $save = $storage->put($fileName, new File($chunk));                 } else {                     $save = $storage->append($fileName, file_get_contents($chunk));                 }                  sleep(1);                  if ($save) {                     return response()->json([                         'type' => 'success',                         'message' => 'Файл успешно загружен',                     ], 200);                 }             } catch (Exception $e) {                 return response()->json([                     'type' => 'error',                     'message' => 'Ошибка загрузки файла',                 ], 500);             }         }     }

public function upload(Request $request) { if ($request->hasFile('chunk')) { $data = $request->all(); $chunk = $request->file('chunk'); // Имя файла $fileName = $data['name']; $exlodeName = explode('.', $fileName); $fileExtension = $exlodeName[count($exlodeName) - 1]; $fileName = md5($fileName) . '.' . $fileExtension; $storage = Storage::disk('public'); try { if ($data['number_chunk'] === 1) { $save = $storage->put($fileName, new File($chunk)); } else { $save = $storage->append($fileName, file_get_contents($chunk)); } sleep(1); if ($save) { return response()->json([ 'type' => 'success', 'message' => 'Файл успешно загружен', ], 200); } } catch (Exception $e) { return response()->json([ 'type' => 'error', 'message' => 'Ошибка загрузки файла', ], 500); } } }

Вообще правильно ли я делаю или есть более удобный и правильный вариант (без плагинов/компонентов и т.п.)? Заранее спасибо.

Дополнительно:

Решено. Спасибо за наводку YepBro на счёт сверки файлов побайтово. Это дало понять что не правильно записывал файл.
Решение:

$save = $storage->append($fileNameBlob, file_get_contents($chunk));

$save = $storage->append($fileNameBlob, file_get_contents($chunk));

поменять на

$save = file_put_contents(storage_path('/app/public/' . $fileNameBlob), file_get_contents($chunk), FILE_APPEND | LOCK_EX);

$save = file_put_contents(storage_path('/app/public/' . $fileNameBlob), file_get_contents($chunk), FILE_APPEND | LOCK_EX);

Флаг "LOCK_EX", наверное, необязателен. Но ради блокировки записи я его поставил.

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Роман IT Ответ

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

1. Используем библиотеку FFmpeg для разделения видеофайла на фрагменты. FFmpeg - это мощный инструмент для обработки видео и аудио файлов. Установите FFmpeg на свой компьютер.

2. Создайте PHP скрипт, который будет вызывать FFmpeg и разделять видеофайл на небольшие фрагменты. Ниже приведен пример кода:

$videoPath = 'путь_к_видеофайлу.mp4';
$outputPath = 'путь_к_папке_для_фрагментов/';
$fragmentDuration = 10; // длительность каждого фрагмента в секундах
 
exec("ffmpeg -i $videoPath -c copy -segment_time $fragmentDuration -f segment $outputPath%d.mp4");

$videoPath = 'путь_к_видеофайлу.mp4'; $outputPath = 'путь_к_папке_для_фрагментов/'; $fragmentDuration = 10; // длительность каждого фрагмента в секундах exec("ffmpeg -i $videoPath -c copy -segment_time $fragmentDuration -f segment $outputPath%d.mp4");

3. После того, как видеофайл будет разделен на фрагменты, вы можете загрузить их на сервер. Для этого воспользуйтесь стандартным методом загрузки файлов в PHP, например, с использованием функции move_uploaded_file.

4. При загрузке фрагментов на сервер, убедитесь, что у вас достаточно места для хранения всех фрагментов видеофайла.

5. После загрузки всех фрагментов на сервер, вы сможете объединить их обратно в единый видеофайл, если это необходимо.

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

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно