How to Reduce Video Size - iOS Titanium Video? - ios

I am developing an iOS application in Titanium Appcelerator and using inbuilt camera to record a 2-5 minutes video. Once the video is recorded it needs to be passed to a PHP Web application via REST API. However the size of this video is too big [almost 100 Mb] to be transferred successfully.I am looking for a way to either compress the video or reduce its size to be able to upload successfully.Your suggestions are valuable , so kindly let me know what is the best way forward.
Thank you for your time

You could try a module developed by me: ti.ios.trim (originally built to do video trimming, but it also supports video compression). You could leave out the startTime and the endTime parameters and do something like the following:
Ti.Media.showCamera({
mediaTypes: [Titanium.Media.MEDIA_TYPE_VIDEO],
success: function(e) {
var tempFile = Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, new Date().getTime() +'-'+ _.random(0,1000) +'.mov');
tempFile.write(e.media);
compressVideo(tempFile.resolve());
}
});
function compressVideo(pathToVideoFile) {
var trimmer = require('ti.ios.trim');
trimmer.trimVideo({
input: pathToVideoFile,
quality: 1, // use 1 for high compression or 2 for medium compression
success: function(e) {
Ti.API.info('SUCCESS:');
Ti.API.info('path to the compressed file: '+ e.videoURL);
},
error: function(e) {
Ti.API.error('ERROR:');
Ti.API.info(JSON.stringify(e));
}
});
}

Related

React Native HTML to PDF not displaying local images

In case you guys don't know, there was a problem previously with this library not rendering local images on Android as well, but apparently it was solved. Now, I'm facing the exact same issue on iOS, with a difference that I can use static images like assets/src/assets/images/logo.png. But when the images start with something like file:///, storage://, ph:// it simply does not get rendered.
What I'm doing is trying to generate a PDF report file, which must be generated independently the user has an internet connection or not. That is the reason why I have to use local images.
The static image is the logo of the company, and the local image which is not getting rendered is an image saved to the phone's storage through Image Picker or Camera Roll. The React Native Image component displays the image perfectly, so I don't think I'm using a wrong path.
What I have tried so far:
Removing the file:/// or storage:// or ph:// from the beginning of the path string;
In some cases, when I save an image to the phone's library with Camera Roll, it will return a path that starts with ph:// but without an extension, such as .jpg or .png. I tried to put the extension manually, and still does not make any difference;
I tried to convert the image to base64 using rn-fetch-blob (with RNFetchBlob.fs.base64.encode(path)), but still got no success.
Devices:
iPhone SE with iOS 14 (also simulator iPhone 11 with iOS 15)
MacBook Air 2017 Core i5 1.8GHz and 8gb RAM (macOS Big Sur 11.5.2)
Environment
node: 12.22.7
npm: 6.14.15
react: 16.9.0
react-native: 0.61.5
react-native-html-to-pdf: ^0.11.0 (updating it to 0.12.0 also got me the same result)
Code:
sharePDF = async () => {
try {
this.changeVisibilityOptions(false);
this.changeVisibilityLoading('Gerando PDF...');
let htmlTemplate = '';
htmlTemplate = await getPDFDespesa(this.state);
const pdfOptions = {
html: htmlTemplate,
fileName: 'RelatorioDespesas',
directory: 'Relatorios'
};
let pdfFile = await RNHTMLtoPDF.convert(pdfOptions);
this.changeVisibilityLoading(false);
const shareOptions = {
title: 'Compartilhar com:',
url: `file://${pdfFile.filePath}`,
type: 'application/pdf',
failOnCancel: false
};
const ShareResponse = await Share.open(shareOptions);
} catch (error) {
this.setState({ visibilityLoadingScreen: false });
console.log('Error =>', error);
}
}
Final thoughts:
Well, since the code is stored at a private repository, I can't show the whole thing here for ethical reasons. But I'm doing my best to give you as much details as possible.
The output the code produces an almost complete PDF, with the only point that I see broken image icons where the images were supposed to be. For Android it works perfectly now.
I think this might be an issue related to WebView, since react-native-html-to-pdf uses WebView to generate the PDF from HTML code. I reached this conclusion after another developer at my job was trying to create a screen with a preview of the PDF before it could be shared got the very same problem for both Android and iOS. The library he used was react-native-webview.
Update with solution
Alright guys, after a long time of research, me and a colleague got to a solution which may not be the best but does what we expected.
First of all, one thing that was discovered is that we have to divide the problem in two, because we actually had two problems.
Images from react-native-image-picker: After a long time trying to find the problem which was preventing the local images from getting rendered, I tried updating the library to version 4.7.3 (latest version at that day) and did a number of required changes to the code, as the version we were using was considerably aged. Well, it happened to work out for my surprise, even with the response uri's format not being changed;
Images from #react-native-community/cameraroll: This one was a bit more complicated. It took me some time to realize that the iOS' PHAsset was not supported in the WebView or react-native-html-to-pdf (which uses WebView in background). So, after some research, me and my colleague found a workaround that lead us to a relatively easy solution. Basically we used react-native-fs to copy the PHAsset media file to a temporary directory, which would return a uri that started with file:// and could be rendered by WebView. That's the code we used to do this:
export default function getImageNameFromUrl(imageUrl = "") {
if (imageUrl) {
const splittedImageUrl = imageUrl.split('/');
return splittedImageUrl.pop();
}
return null;
};
export default async function copyAssetsFileIOSAndReturnURI(remoteURL = '', localURI = '') {
try {
if (remoteURL && localURI) {
const imageName = getImageNameFromUrl(remoteURL);
const imgPath = await RNFS.copyAssetsFileIOS(localURI, RNFS.TemporaryDirectoryPath+imageName, 0, 0);
return imgPath;
}
return null;
} catch (err) {
console.log(err);
return null;
}
}

Wrong duration in MediaRecorder stream on iOS

I am trying to use multiple files with ffmpeg and I am having a problem with the duration of the files created through iOS devices.
I am recording the videos through the webcam of the device with:
mediaRecorder.current = new MediaRecorder(videoPlayer.current.srcObject);
mediaRecorder.current.start();
mediaRecorder.current.ondataavailable = (e) => {
setVideoCreatedData(e.data);
};
Then I am downloading the file to my computer and testing the metadata through https://www.metadata2go.com/ and this is the output:
As you can see, the duration is 0s.
I want to then use this file with ffmpeg, however, it does not detect the duration and therefore I am experiencing problems.
How should I record the video in order to get a proper duration on the file's metadata?

Downloading large pdf files in a Flutter app

I'm looking for a way to download large pdf files from an external server with a Flutter application for offline storage.
But downloading a large file (sometimes 100mb+) takes some time. I don't want the app being stuck in a wait function for it to download. What i'm looking for is a download function that has a callback with a progress report (Something like: 250000/500000 bytes done. Doesn't have to be exactly that. Just something that I can work with and make a progress bar out of).
Is this even possible to do in Flutter? The only things I came across were the HTTP library. But that does not seem to have a progress callback and just plainly reading the contents of a http call (Which also doesn't have a progress report). I hope someone has a method for me that I can use to make this happen.
Kind regards,
Kevin Walter
EDIT:
C# has the perfect example of what I mean
https://stackoverflow.com/a/9459441/2854656
https://docs.flutter.io/flutter/dart-io/HttpClient-class.html
https://docs.flutter.io/flutter/dart-io/HttpClientResponse-class.html
int fileSize;
int downloadProgress = 0;
new HttpClient().get('localhost', 80, '/file.txt')
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
fileSize ??= respone.contentLength;
response.transform(utf8.decoder).listen((contents) {
downloadProgres += contents.length;
// handle data
});
});

save image/video to gallery in IOS using cordova flle transfer

I am downloading images/videos from an application created by me in Cordova iOS. I want to access the downloaded files from other applications too, like WhatsApp, Instagram, Telegram etc.
I am able to download files, but am unable to view them in gallery or videos, unable to access filesystem root path in iOS.
Do we have any plugins in Cordova for iOS for moving files from documents directory to camera roll? if not, can you guide me how to achieve it by following the native C process as I am new to C.
Here is my sample code which is working in iOS.
var url = encodeURI("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"); // image url
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fs) {
//cordova.file.documentsDirectory
//cordova.file.dataDirectory
//fs.root.fullPath
//rootdir.toURL();
//fileSystem.root
alert("the root is" + cordova.file.documentsDirectory)
var imagePath = cordova.file.documentsDirectory + "/big_buck_bunny.mp4";
alert(imagePath);
var fileTransfer = new FileTransfer();
fileTransfer.download(url, imagePath, function(entry, imagePath) {
alert(imagePath);
console.log(imagePath);
alert(entry.fullPath); // entry is fileEntry object
// download();
downloadFile();
}, function(error) {
alert("Some error");
});
})
It's not possible with the cordova-plugin-filetransfer. You may want to check https://github.com/driftyco/cordova-camera-roll to save a base 64 encoded image to the camera roll. There's a fork for working with videos, but encoding a big video in base 64 is probably not very efficient.

How to test whether a YouTube video supports HD resolution?

The YouTube API v3 allows you to request information about a video, such as its title, description, etc.
Is there a way to determine whether the video supports HD resolution?
A workaround could be to look for a maxres thumbnail:
var checkURL = "https://www.googleapis.com/youtube/v3/videos?key=XYZ&part=snippet&fields=items(snippet(thumbnails))&id=" + uid;
$.getJSON(checkURL, function(data) {
if (data.items.length > 0) {
/* Verify this video is HD */
if (data.items[0].snippet.thumbnails.maxres == undefined) {
alert("This video does not support HD")
}
}
});
but is there a better approach?
You can check if a video supports HD by reading contentDetails.definition in a video resource:
string
Indicates whether the video is available in high definition (HD) or only in standard definition.
Valid values for this property are: hd, sd

Resources