Developer Question: BxTemplUploaderRecordVideo

I have extended BxTemplUploaderRecordVideo and the record button shows on my form. I can record a video, it posts to form, I get the s3 URL and everything is working.

Now, I override getRestrictionsText and set my message as 'video can only be 30 seconds'. This works. Message is displayed upper left corner.

Now, here is my issue. I have overridden handleUploads and am trying to implement a custom handler before calling

parent::handleUploads ($iProfileId, $mixedFiles, $isMultiple, $iContentId, $bPrivate);

I want to check duration of video before calling the parent method. So, I have tried

$aFile = $_FILES['file'];
$sFile$aFile["tmp_name"];
$iDuration = BxDolTranscoderVideo::getDuration($sFile);

and I've tried switching $aFile to

$aFile = bx_get('file');

But both are null. So I can't check duration of video as I would a regular upload.

How do I get the duration?

Thank you 🙏

  • 385
  • More
Replies (16)
    • 👀

      • @LeonidS @Anton L @Alex T⚜️ @Alexey I've tracked this issue to the fact you are uploading the web capture as a blob, and I'm not sure I can check duration at this point.

        So, I need help understanding the form classes. How do I handle the same check at submit, and if too long, send the error message to the correct place, and the form placed in error mode (error message by submit button, my custom error message by video uploaded)?

        I can't find any good demo or explanation of the error handler.

        Thank you for your time.

        • How to check this???? There are no examples of custom checks on submit. At least direct me to where I can look and understand how this works. I'm actually tired of looking through UNA code for hours to find a one line fix for my issue.

          • Anyone? Lmao.

            • Can someone give me an example where I can check custom checks on form submit. There IS NO DOCUMENTATION!

              • @Andrey Yasko this is exactly what I'm talking about. 12 script kiddie answers from UNA since this was posted. But ask a question that actually requires a detailed answer, and it goes unanswered.

                Not one piece of documentation on form submit check. Not one piece of documentation on returning error message and setting form into 'error' state (not sure what else to call it).

                If you (as UNA collective) don't want to answer developer related questions, provide the documentation. I've read blogs from two years ago saying documentation would be a priority, hold us accountable.

                Well... Here I am.

                Can I get some assistance, or cancel my pro support.

                • Most of that code had been created/written a few years ago. You as a dev should know that in such a case it requires quite some time to recall what and how works there under the hood. :)

                  Anyway answering your question, I think the best approach would be to do a server side check rather than a client side.

                  At the BxBaseUploaderRecordVideo::handleUploads method the $mixedFiles param is actually what you're looking for - it is the $_FILES['file'] array. So you could try to use a call to

                  $iDuration = BxDolTranscoderVideo::getDuration($mixedFiles['tmp_name']);
                  

                  And then in case it exceeds the desired limit then prevent the call to parent::handleUploads and add your error message to

                  $this->_sUploadErrorMessages
                  
                  • Um, thanks for the reply, but you must not have read my discussion at all, as I already found I can not pull from the files array because recordings (WebRTC) is sent back to the server as a blob. So, the normal files array are all null. All are empty.

                    So, I moved on to checking it at form submit. Yet, I can't find any documentation or even a hint of how I do the check at submission.

                    And, as a developer, it should not mean I have to read code, figure out hooks, figure out what classes to extend and what functions to override, without documentation. Otherwise, I'm trying to build an engine from a million parts without a schematic. Yes, I'll eventually get it, but if only I had t schematic. I hope you understand my parable.

                    • The camera recordings are not sent via WebRTC, they are sent as a blob data via an AJAX request and in the end are treated as a regular $_FILES param (in a different variable though). So just try the solution I've provided above. Check the $mixedFiles['tmp_name'] as I suggested - this is the recorded file to be processed.

                      • @Alexander your code produced fatal error due to $mixedFiles['tmp_name'] being an array. So

                        $mixedFiles['tmp_name'][0] does give me the tmp file path.

                        However, $iDuration is always set to false. No duration. Do you know why?

                        • Yes, the $mixedFiles['tmp_name'] is actually an array of files. The line of code I gave wasn't tested and was just to give you a direction.

                          As to the duration - I would assume that ffmpeg which is used to get a duration for some reason fails to determine it from a recorded but not yet transcoded video stream. You can dive deeper into the BxDolTranscoderVideo::getDuration and analyze the response given by ffmpeg there. You may try to use a custom approach to get a video stream duration, may be try a ffprobe instead of ffmpeg.

                          In case you would want to try a client side check instead of a server side check then you can do so by adding your custom verification to inc/js/classes/BxDolUploader.js, see this.submitRecording method.

                          • Further testing, ffmpeg output is:

                            Input #0, matroska,webm, from '/home/wise/tmp/php2HfdWI':
                            Metadata:
                             encoder : QTmuxingAppLibWebM-0.0.1
                             Duration: N/A, start: -0.001000, bitrate: N/A
                             Stream #0:0(eng):
                            

                            So, this is why duration is set to false. And my web recording was 15 seconds.

                            Why?

                            • This is a question to a ffmpeg developers. May be a web recording is not having duration set in a file header, because it was streamed, while ffmpeg relies only on a file header and is not analyzing the entire file. I'm not sure. You may try to update the ffmpeg to a newer version. Or as I suggested above you can try to use a ffprobe utility instead, because it works better for getting various file info than the ffmpeg.

                              • Seems webrtc webm files have no duration / bitrate added to them. Interesting. The solution is to make a quick copy (no transcode) and check the copy, which ffmpeg has added the duration/bitrate headers.

                                Seems like a hack, any proper way to do this @Alexander ?

                                ffprobe is my go to, but it also displays streams duration as empty. I'm afraid getting duration will require a copy made though ffmpeg. Then duration can be read. Then unlink copy.

                                • Also, @Alexander , thank you for your time. It is very appreciated. Sometimes a little guidance will send me on the path I need to find my solution.

                                  For now, I'm taking the tmp file and pushing it through ffmpeg as a copy and then reading duration from copy. Unlinking the copy.

                                  This works. Since copy function of ffmpeg has little overhead, I doubt this will be an issue under heavy load.

                                  • Here is working code:

                                    // wise 5.30.24 - webm stream duration hack
                                    $sFile = $mixedFiles['tmp_name'][0];
                                    $sTempFile = BX_DIRECTORY_PATH_ROOT.'tmp/'.basename($sFile).'.webm';
                                    
                                    $command = BX_SYSTEM_FFMPEG . ' -i ' . $sFile . ' -vcodec copy -acodec copy '.$sTempFile.' 2>&1';
                                    $output = shell_exec($command);
                                    
                                    $iDuration = BxDolTranscoderVideo::getDuration($sTempFile);
                                    @unlink($sTempFile);
                                    

                                    Works like a charm. Figured I'd post my code so anyone else needing this can benefit.

                                    😎👍

                                    Login or Join to comment.