Expo video compression

Currently I’m using expo 36. I’m struggling to compress video. Image manipulator works for images but not able to compress video. Also I don’t want to eject the project as of now so is there any other way?

2 Likes

Hi @abhijeet_ardouro any luck with this?

Any updates by chance?

Wow, nothing huh? Gotta love a responsive team.

What did you find out? This forum is basically dead

I did a workaround and still hoping to upgrade it because it is extremely clunky and needs some love but it allows users to upload their videos to a pro Vimeo account, where Vimeo takes care of the compression. And oddly enough it works. Also, It looks like I need to try catch this for when things don’t go as planned but hopefully there is something helpful here for someone who needs a fix for this. I still have to believe there is a better solution out there and I will continue searching for it. I am using firebase firestore to hold all the data and eventually, as you can see in the code the uploaded video/image url is sent as part of the post that is generate.

Here is the function I am using to pick the image/video:

 const pickImageFunc = async () => {
    const loadingImage = require("../../assets/upload-image-loading.png");
    const picPath = `/kosmique/posts/${currentUserUID}/${Math.round(
      Math.random() * 100000000
    )}`;
  
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: false,
      aspect: [4, 4],
      quality: 1,
      includeBase64: false,
    });
    let info;
  
    if (!result.canceled) {
      const asset = result.assets[0];
      let fileFormat, resultUrl;
      setBlankImage(loadingImage);
      if (asset.uri.includes("quicktime") || asset.uri.includes(".mov")) {
        fileFormat = "video/quicktime";
      } else if (asset.uri.includes("mp4")) {
        fileFormat = "mp4";
      }
  
      setErrorMessage("");
      if (
        asset.uri.includes("data:video") ||
        asset.uri.includes(".mov") ||
        asset.uri.includes(".mp4")
      ) {
        info = await returnVideoResultUrl(result, picPath, fileFormat);
  
        const theBody = {
          upload: {
            approach: "pull",
            size: info.metadata.size,
            link: info.remoteURL,
          },
        };
  
        fetch("https://api.vimeo.com/me/videos", {
          method: "POST",
          headers: new Headers({
            Authorization: `Bearer ${envVars.VIMEO_TOKEN}`,
            "Content-Type": "application/json",
          }),
          body: JSON.stringify(theBody),
        })
          .then((response) => response.json())
          .then((data) => {
            setPostObj({
              ...postObj,
              image:info.remoteURL,
              media:data.uri.replace("/videos/", ""),
              mediaType: 'video',
            })
          })
          .catch((error) => {
            console.error("Error:", error);
          });
      } else {
        resultUrl = await returnImageResultUrl(asset, picPath);

        setPostObj({
          ...postObj,
          image:resultUrl.remoteURL,
          media:resultUrl.remoteURL,
          mediaType: 'image',
        })
      }
      setReadyToSubmit(true);
    }
  };

Here is the function I use to interface with the Firebase and Vimeo. This step may be able to be condensed into the uploadImage functionality on the next function.

import { uploadImage } from '../API/firebaseMethods';

export default async function returnVideoResultUrl(
  result,
  picPath,
  fileFormat
) {
  if (!result.cancelled) {
    const resultUrl = await uploadImage(picPath, result.uri, fileFormat);
    return resultUrl;
  }
}

the naming of this function is slightly misleading, it uploads images and videos to their respective destinations


export const uploadImage = async (picPath, image, format) => {

  // Implement a new Blob promise with XMLHTTPRequest

  const blob = await new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.onerror = function () {
      reject(new TypeError("Network request failed"));
    };
    xhr.responseType = "blob";
    xhr.open("GET", image, true);
    xhr.send(null);
  });

  // Create a ref in Firebase (I'm using my user's ID)
  const ref = firebase.storage().ref().child(picPath);

  // Upload blob to Firebase
  const snapshot = await ref.put(blob, { contentType: format });

  // Create a download URL
  const remoteURL = await snapshot.ref.getDownloadURL();
  const metadata = await snapshot.ref.getMetadata();
  // Return the URL
  return { remoteURL, metadata };
};

See also: