Set up a bidirectional communication channel using Reverb. If you want real-time client comms, you'll need the appropriate infrastructure for it.
How to add realtime progress bar while submitting a form
I am using laravel to upload a video file. I want to show realtime progress bar there.
There is a form for video upload with many extra inputs. For the video I am using FFMPEG to crop and encrypt videos. This takes time.
My form is:
<div class="row" style="margin-top: 10px;">
<div class="col-lg-6">
<div class="form-group">
<label for="video_price">Select Video<b class="red">*</b></label>
<input id="vide_Upload" type="file" name="vide_Upload"
style="opacity: 0; position: absolute; z-index: -1;" accept="video/*" />
<label for="vide_Upload" id="file-drag">
Select a file to upload (Maximum allowed mp4 file size is 100 MB)
<br />OR
<br />Drag a file into this box
<br /><br /><span id="vide_Upload-btn" class="button">Add a video</span>
</label>
</div>
</div>
<div class="col-lg-6 video-details">
<div class="form-group">
<div class="custom-control">
<div id="file-details"></div>
</div>
<div class="progress videoProgressBar mt-2" style="display:none;">
<div class="progress-bar" role="progressbar" aria-valuenow="" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
Showing only file upload input field. There are some other fields as well.
I am using ajax to submit:
$.ajax({
url: '{{ route('video.store') }}',
type: "POST",
data: formData,
processData: false,
contentType: false,
cache: false,
beforeSend: function () {
$('.videoProgressBar').show();
// Start the interval to update the progress bar
progressBarInterval = setInterval(function() {
// Increment the progress bar by a fixed amount
var currentWidth = $('.progress .progress-bar').width();
var maxWidth = $('.progress .progress-bar').parent().width();
var increment = maxWidth / 100; // Assuming 100 intervals for 100%
if (currentWidth + increment <= maxWidth) {
$('.progress .progress-bar').css('width', currentWidth + increment);
} else {
clearInterval(progressBarInterval);
}
}, 5000); // Update every second
},
success: function(response) {
clearInterval(progressBarInterval); // Stop the progress bar interval
$('#videoSubmit').html('Submit Your Video');
$("#videoSubmit"). attr("disabled", false);
if (response.success == 'error') {
var currentWidth = '0';
var increment = '0'; // Assuming 100 intervals for 100%
$('.progress .progress-bar').css('width', currentWidth + increment);
$('#videoSubmit').html('Submit Your Video');
$("#videoSubmit").attr("disabled", false);
$('.errorDisplayDiv').html(response.message);
$('html, body').animate({
scrollTop: 0
}, 0);
$('.successDiv').slideDown('slow', function() {
/*setTimeout(function() {
$('.successDiv').slideUp('slow');
}, 5000);*/
});
} else {
var currentWidth = '100';
var increment = '100'; // Assuming 100 intervals for 100%
$('.progress .progress-bar').css('width', currentWidth + increment);
window.location.href = response.redirect;
}
},
error: function(xhr, status, error) {
var errors = JSON.parse(xhr.responseText).errors;
$.each(errors, function(key, value) {
if(key == 'captcha')
{
$("#" + key + "_videos-error").html(value[0]);
}
else
{
$('.errorDisplayDiv').html('Something went wrong. Please try again');
$('.successDiv').show();
$('html, body').animate({
scrollTop: 0
}, 0);
}
});
reloadCaptcha_video();
setTimeout(function() {
// Clear the interval when the error occurs
clearInterval(progressBarInterval);
}, 1000); // Stop the interval after 10 seconds (adjust as needed)
var currentWidth = '';
var increment = ''; // Assuming 100 intervals for 100%
$('.progress .progress-bar').css('width', currentWidth + increment);
$('#videoSubmit').html('Submit Your Video');
$("#videoSubmit").attr("disabled", false);
}
});
Currently progress bar increases on every 5 seconds. If video file takes time then progress bar shows complete. Because progress bar increases on every 5 seconds.
controller is:
ublic function store(Request $request)
{
$validatedData = $request->validate([
'video_title' => 'required',
'keywords' => 'required',
'references' => 'required',
'abstract' => 'required',
'declaration_of_interests' => 'required',
'declaration_remark' => 'required_if:declaration_of_interests,2',
'videotype_id' => 'required',
'videosubtype_id' => 'required',
'majorcategory_id' => 'required',
'subcategory_id' => 'required',
'terms_n_conditions' => 'required',
'membershipplan_id' => 'required',
'vide_Upload' => 'required|mimes:mp4|max:100000',
'captcha' => 'required|captcha'
], [
'required' => 'This field is required',
'declaration_remark.required_if' => 'This field is required',
'captcha.captcha' => 'Invalid captcha'
]);
DB::beginTransaction();
try {
$filteredKeywords = array_filter($request->keywords, function ($value) {
// Remove null values from the array
return $value !== null;
});
$uniquen_number = $this->generateUniqueNumber();
$videoupload = new Videoupload();
$videoupload->user_id = Auth::id();
$videoupload->unique_number = $uniquen_number;
$videoupload->videostatus_id = 1;
$videoupload->videotype_id = $request->videotype_id;
$videoupload->videosubtype_id = $request->videosubtype_id;
$videoupload->majorcategory_id = $request->majorcategory_id;
$videoupload->subcategory_id = json_encode($request->subcategory_id);
$videoupload->video_title = $request->video_title;
$videoupload->keywords = json_encode($filteredKeywords);
$videoupload->references = $request->references;
$videoupload->abstract = $request->abstract;
$videoupload->declaration_of_interests1 = $request->declaration_of_interests;
$videoupload->acknowledge = $request->acknowledge;
$videoupload->doi_link = $request->doi_link;
if($videoupload->declaration_of_interests1 == 2)
{
$videoupload->declaration_remark = $request->declaration_remark;
}
$videoupload->membershipplan_id = $request->membershipplan_id;
$videoupload->terms_n_conditions = $request->terms_n_conditions;
if($request->hasFile('vide_Upload')){
$major_category_details = get_majorcategories($request->majorcategory_id);
$folderName = str_replace(' ', '_', $major_category_details->category_name);
$vide_Upload2_image = $request->file('vide_Upload');
$extension = $vide_Upload2_image->getClientOriginalExtension();
$newFileName = $uniquen_number . '.' . $extension;
$newFileName_cropped_file = $uniquen_number . '_cropped.' . $extension;
//$new_directory = mkdir('app/public/uploads/Videos_to_Revise/'.$folderName.'/'.$uniquen_number, 0777, true);
$filePath = $vide_Upload2_image->storeAs('uploads/Videos_to_Revise/'.$folderName.'/'.$uniquen_number, $newFileName, 'public');
$video_path_url = asset(Storage::url($filePath));
// Start crop the video
$video_path = storage_path('app/public/uploads/Videos_to_Revise/'.$folderName.'/'.$uniquen_number.'/'.$newFileName);
$croppedVideoPath = storage_path('app/public/uploads/Videos_to_Revise/'.$folderName.'/'.$uniquen_number.'/'.$newFileName_cropped_file);
$cropped_video_path_url = url('/storage/uploads/Videos_to_Revise/' . $folderName.'/'.$uniquen_number . '/' . $newFileName_cropped_file);
//$ffmpegCommand = "C:/FFmpeg/bin/ffmpeg -i " . $video_path . " -ss 00:00:00 -t 00:00:20 " . $croppedVideoPath;
$ffmpegCommand = "ffmpeg -i " . $video_path . " -ss 00:00:00 -t 00:00:20 " . $croppedVideoPath;
$test = exec($ffmpegCommand);
// End crop the video
// start encrypting the videos
$highBitrate = (new X264)->setKiloBitrate(1000);
//start encrypting fulllength files
FFMpeg::fromDisk('public')
->open($filePath) // Provide the path relative to the 'local' disk
->exportForHLS()
->withRotatingEncryptionKey(function ($filename, $contents) use ($folderName,$uniquen_number) {
Storage::disk('public')->put('uploads/Videos_to_Revise/'.$folderName.'/'.$uniquen_number . '/encrypted_files/' . $filename, $contents);
})
->addFormat($highBitrate)
->save('uploads/Videos_to_Revise/'.$folderName.'/'.$uniquen_number . '/encrypted_files/'.$uniquen_number.'.m3u8');
//end encrypting fulllength files
//start encrypting cropped files
FFMpeg::fromDisk('public')
->open('uploads/Videos_to_Revise/'.$folderName.'/'.$uniquen_number.'/'.$newFileName_cropped_file) // Provide the path relative to the 'local' disk
->exportForHLS()
->withRotatingEncryptionKey(function ($filename, $contents) use ($folderName,$uniquen_number) {
Storage::disk('public')->put('uploads/Videos_to_Revise/'.$folderName.'/'.$uniquen_number . '/encrypted_files/' . $filename, $contents);
})
->addFormat($highBitrate)
->save('uploads/Videos_to_Revise/'.$folderName.'/'.$uniquen_number . '/encrypted_files/'.$uniquen_number.'_cropped.m3u8');
FFMpeg::fromDisk('public')
->open('uploads/Videos_to_Revise/'.$folderName.'/'.$uniquen_number.'/'.$newFileName_cropped_file) // Provide the path relative to the 'local' disk
->getFrameFromSeconds(3)
->export()
->save('uploads/Videos_to_Revise/'.$folderName.'/'.$uniquen_number . '/'.$uniquen_number.'_screenshot.webp');
//end encrypting cropped files
// end encrypting the videos
$videoupload->full_video_url = $video_path_url;
$videoupload->short_video_url = $cropped_video_path_url;
$videoupload->main_folder_name = 'Videos_to_Revise';
$videoupload->category_folder_name = $folderName;
$videoupload->uploaded_video = $newFileName;
}
$videoupload->save();
DB::commit();
return response()->json(['success'=>'Successfully','redirect' => route('my.account')]);
} catch (\Exception $e) {
// Rollback the transaction if any operation fails
DB::rollBack();
// Log or handle the exception
// For example:
// Log::error($e->getMessage());
// Return error response
return response()->json(['error' => $e->getMessage()]);
}
}
Into the method there is using FFMEG to crop, encrypt and take screenshot of the videos.
How can I add here real time progressbar. Thank you in advance!
Please or to participate in this conversation.