admin管理员组

文章数量:1308118

I need to upload file (audio/video) using default input type='file' and the I should pass duration of the video in api request, how i ca do this?

  const uploadFile = async (event) => {
    let file = await event.target.files[0];
    //here api POST request where i should pass duration
   }:

I need to upload file (audio/video) using default input type='file' and the I should pass duration of the video in api request, how i ca do this?

  const uploadFile = async (event) => {
    let file = await event.target.files[0];
    //here api POST request where i should pass duration
   }:
Share Improve this question asked Mar 1, 2021 at 13:15 wefwef цуаefwefwefwef цуаefwef 971 silver badge7 bronze badges 8
  • Simply create a blob URL and append this into some virtual tag, once meta data will be loaded you can get the duration and pass it to your api request. – Shubham P Commented Mar 1, 2021 at 13:17
  • @ShubhamPrajapat I'll be very grateful if you make me an example. – wefwef цуаefwef Commented Mar 1, 2021 at 13:20
  • Sure, will share in few minutes. – Shubham P Commented Mar 1, 2021 at 13:23
  • Just posted an answer. – Shubham P Commented Mar 1, 2021 at 13:41
  • @ShubhamPrajapat unfortunately in returns NaN – wefwef цуаefwef Commented Mar 1, 2021 at 13:41
 |  Show 3 more ments

3 Answers 3

Reset to default 6

You can get the audio duration with HTMLMediaElement.duration:

async function getDuration(file) {
 const url = URL.createObjectURL(file);

 return new Promise((resolve) => {
   const audio = document.createElement("audio");
   audio.muted = true;
   const source = document.createElement("source");
   source.src = url; //--> blob URL
   audio.preload= "metadata";
   audio.appendChild(source);
   audio.onloadedmetadata = function(){
      resolve(audio.duration)
   };
 });
}

Then in your function:

const uploadFile = async (event) => {
   let file = event.target.files[0];
    //here api POST request where i should pass duration
   const duration = await getDuration(file);
 }:

You just need to create an element based on user input(video/audio) and get the duration property -

const VIDEO = "video",
        AUDIO = "audio";
      const uploadApiCall = (file, data = {}) => {
        // ----- YOUR API CALL CODE HERE -----
        document.querySelector("#duration").innerHTML = `${data.duration}s`;
        document.querySelector("#type").innerHTML = data.type;
      };

      let inputEl = document.querySelector("#fileinput");
      inputEl.addEventListener("change", (e) => {
        let fileType = "";
        let file = inputEl.files[0];
        if (file.type.startsWith("audio/")) {
          fileType = AUDIO;
        } else if (file.type.startsWith("video/")) {
          fileType = VIDEO;
        } else {
          alert("Unsupported file");
          return;
        }

        let dataURL = URL.createObjectURL(file);
        let el = document.createElement(fileType);
        el.src = dataURL;
        el.onloadedmetadata = () => {
          uploadApiCall(file, {
            duration: el.duration,
            type: fileType
          });
        };
      });
 <form>
      <input type="file" accept="video/*,audio/*" id="fileinput" />
      <hr />
      Type:<span id="type"></span>
      <br />
      Duration:<span id="duration"></span>
    </form>

In Vue 3 JS, I had to create a function first:

const getDuration = async (file) => {
      const url = URL.createObjectURL(file);

      return new Promise((resolve) => {
        const audio = document.createElement("audio");
        audio.muted = true;
        const source = document.createElement("source");
        source.src = url; //--> blob URL
        audio.preload = "metadata";
        audio.appendChild(source);
        audio.onloadedmetadata = function(){
            resolve(audio.duration)
        };
      });
    }

The user would select an MP3 file. Then when it was submitted I could call that function in the Submit function:

    const handleAudioSubmit = async () => {
      console.log('Your Epsiode Audio is being stored... please stand by!')
      if (file.value) {

        // returns a number that represents audio seconds
        duration.value = await getDuration(file.value)

        // remove the decimals by rounding up
        duration.value = Math.round(duration.value)
        console.log("duration: ", duration.value)

        // load the audio file to Firebase Storage using a posable function
        await uploadAudio(file.value)
    
        .then((downloadURL) => {
          // posable function returns Firebase Storage location URL
          epAudioUrl.value = downloadURL
        })

        .then(() => {
          console.log("uploadAudio function finished")
        })

        .then(() => {
          // Set the Album Fields based on the album id to Firestore DB
          const updateAudio = doc(db, "artist", artistId.value, "albums, albumID.value);
          updateDoc(updateAudio, {
            audioUrl: audioUrl.value,
            audioDuration: duration.value
          })
          console.log("Audio URL and Duration added to Firestore!")
        })
        .then(() => {
          console.log('Episode Audio has been added!')
          router.push({ name: 'Next' })
        })
      } else {
        file.value = null
        fileError.value = 'Please select an audio file (MP3)'
      }
    }

This takes some time to run and needs refactoring, but works provided you allow the async functions the time to finish. Hope that helps!

本文标签: javascriptHow I can know audiovideo duration before uploadingStack Overflow