Video compression in react native using ffmpeg - react-native

I trying to compress video in react native using react-native-ffmpeg .
I am picking video using react-native-image-picker.
I tried using command -y -i ${inputVideo} -vcodec h264 -acodec mp3 ${finalVideo}.
But it is failing with rc:1.
My code:-
RNFFmpeg.execute(
str_cmd,
).then(result => {
if (result.rc === 0) {
console.log("successfully compressed");
} else {
console.log("error",result);
}
});
Thanks!

If I remember correctly, you have to include the input video into the directory for your app.
You should be able to do so with react-native-fs.
And here is the relevant code from the react-native-ffmeg example project.

Related

<video> tag. DOMException: The element has no supported sources, when not utilizing require()

I am trying to play a video when developing locally with VueJS 2.
My code is the following :
<video class="back_video" :src="`../videos/Space${videoIndex}.mp4`" id="background-video"></video>
...
data :
function() {
return {
videoIndex:1
}
}
...
const vid = document.getElementById("background-video");
vid.crossOrigin = 'anonymous';
let playPromise = vid.play();
if (playPromise !== undefined) {
playPromise.then(function() {
console.log("video playing");
}).catch(function(error) {
console.error(error);
});
}
This code is causing the exception given in title. Tried in several browsers, always the same.
If I change the src by :
:src="require(`../videos/Space${videoIndex}.mp4`)"
it works.
But in that case building time is very long as I have many different videos in my videos directory, because adding require() will force to copy all videos in the running directory at build phase (vue-cli serve), and this is really annoying. In other words I want to refer videos that are outside the build directory to avoid this (but also to avoid having videos in my git).
It is interesting to note that when I deploy server side, it works perfectly with my original code
:src="`../videos/Space${videoIndex}.mp4`"
Note also that if i replace my code with simply
src="../videos/Space1.mp4"
it works too. So the video itself, or its location, are not the source of the problem.
Any clue ?
You can host your videos on a CDN to have something faster and easier to debug/work with.
Otherwise, it will need to bundle it locally and may take some time.

How to display a thumbnail of a local video

Do you know a lib / a way to display a thumbnail of a local video ?
I select a video from my device with react-native-image-picker and i would like to display a thumbnail of this video in a View or flatlist in case of several selections
You can use below plugin for get thubmnail form local path
https://github.com/phuochau/react-native-thumbnail#readme
import RNThumbnail from 'react-native-thumbnail';
let getFilePath = ''
RNThumbnail.get(filepath).then((result) => {
console.log(result.path); // thumbnail path
getFilePath = result.path;
})
After getting path for display purpose you can use react-native-video for play and display
react-native-video and use below code
<Video source={{ uri: getFilePath }} pause={true} />
Hope this will work for you.
If you are using Expo and you are not deploying to web, this package will do the job for you: https://docs.expo.dev/versions/latest/sdk/video-thumbnails/

React-native packager configuration - How to include .zip file in bundle?

My problem:
I have a zip file that contains a firmware update for my company's device
I want to be able to access it using react-native-fs with the code below
.
export function readAssetFile(name) {
if(Platform.OS === 'ios') {
return RNFS.readFile(`${RNFS.MainBundlePath}/assets/data/${name}`);
} else {
return RNFS.readFileAssets(`raw/${name}`, 'base64');
}
}
My project structure looks like:
ProjectDir
android
data
image1.png
image2.png
firmwarefile.zip
ios
The android branch works, because I added a build step in my .gradle to copy firmwarefile.zip into ProjectDir/android/app/src/main/assets/raw. So I can call readAssetFile('firmwarefile.zip'), and it returns the data.
On iOS, all the image files (Image1.png, Image2.png) are included in MyProject.app/assets/data/ without me having to do anything, but the zip file that sits beside them is not.
Looking into the actual packager code (from the metro project), it seems (based on metro/src/defaults.js) that zip files aren't included by default by the packager, but the packager can be configured to include other file types. But I can't find any documentation for how I'd go about doing that configuring.
Sorry for what feels like a really simple question, but I've been trying to get this zip included in my bundle for ~4 hours now. I'm resorting to manually putting in console.logs and error-throws to trace things inside metro to try and find where I should be sending in my config.
Versions:
React-native: 0.55.3
Metro: 0.30.2
This is a hack, but it gets it done:
Convert your zip binary to a base64 string
Stick it in a .js file, a la module.exports = "<your base64 data goes here>"
In your file that needs the zip file, use import myZipFileAsBase64 from './hacky-base64-file.js';
Here's a quick script to make your base64 files:
var fs = require('fs');
function prepareZip(file, outJs) {
const b64 = fs.readFileSync(file, 'base64');
fs.writeFileSync(outJs, `module.exports = ${JSON.stringify(b64)};`);
}
prepareZip('./data/myFirmware.zip', './hacky-base64-file.js');

Can't get my video played with Qt Multimedia and gstreamer

I've just installed gstreamer on my Debian Jessie linux.
I actually plan to use it within QtMultimedia framework. And though I'm familiar with vlc...I'm new in gstreamer's world.
I tried to run the following very basic qml program:
Window {
visible: true
MediaPlayer {
id: mediaplayer
source: "file:///home/kai/Videos/testx264.mp4"
}
VideoOutput {
anchors.fill: parent
source: mediaplayer
}
MouseArea {
id: playArea
anchors.fill: parent
onPressed:
{
mediaplayer.play()
console.log("error = ", mediaplayer.errorString)
}
}
}
When I try to play the video, I get the sound but no video. In the application output I get the logs below:
Warning: "No decoder available for type 'video/x-h264, stream-format=(string)avc, alignment=(string)au, level=(string)3.1, profile=(string)high, codec_data=(buffer)0164001fffe1001e6764001fac56240b435f9f016a040402800000030080000032478c18c4c001000668e88e1f2c8b, width=(int)720, height=(int)404, framerate=(fraction)50/1, pixel-aspect-ratio=(fraction)1/1, parsed=(boolean)true'."
qml: error = Cannot play stream of type: <unknown>
However, if I launch gstreamer command line as follow, I can get the video playing correctly:
gst-launch-1.0 filesrc location=/home/kai/Videos/testx264.mp4 ! decodebin name=decoder decoder. ! videoconvert ! xvimagesink decoder. ! audioconvert ! pulsesink
I don't really understand what's happening. I was wondering if my version of Qt was maybe statically link with some gst stuff ?
I have installed Qt 5.5 with regular Linux installer.
Should I set some specific settings ?
Should I recompile a specific Qt component respectively ?
Z.

How to offer files for download?

I have a problem. In my sencha touch application I have list items like .pdf, .png, ... If user taps on one of them file should be download on his mobile device.
How can I do this? I have no idea :-)
Thanks for help.
You can use phonegap file api to download files, If you are using sencha touch 2.3 or above just follow the bellow steps.
Install phonegap in sencha project by executing following command at the project root and this command creates phonegap folder inside project root.
sencha phonegap init
You need to install two phonegap plugins to work with file api by executing two following commands inside phonegap folder.
$ phonegap local plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-file.git
$ phonegap local plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer.git
Now you can start working file api in sencha touch and you can follow below code i used for one of my project.
If you want to download file, first you need to read device file system and then using file system you can download files.
getFileSystem : function(){
var me =this;
Ext.Viewport.mask({
xtype: 'loadmask',
message: 'Downloading files..'
});
var extfs = Ext.create("Ext.device.filesystem.Cordova");
extfs.requestFileSystem({
type: window.PERSISTENT,
size: 1024 * 1024,
success: function(fSys) {
window.fileSys = fSys;
Ext.Viewport.unmask();
me.fileDownload("myfolder/filename.png","http://someurl");
},
failure: function(error){
alert(error);
Ext.Viewport.unmask();
}
});
}
I am passing fileLocation(location you want to store file inside phone) & url in above function.
fileDownload: function(fileLocation,Url){
Ext.Viewport.mask({
xtype: 'loadmask',
message: 'Downloading files..'
});
var me = this;
var fSys = window.fileSys
if(fSys){
var file = Ext.create('Ext.device.filesystem.FileEntry',
fSys.fs.root.toURL() + fileLocation, fSys);
file.download({
source: Url,
success: function(entry){
Ext.Msg.alert('SUCCESS', 'Image successfully downloaded');
Ext.Viewport.unmask();
},
failure: function(error){
Ext.Msg.alert('ERROR', 'Download failed');
Ext.Viewport.unmask();
}
});
}
}
Now can see image at internalMemorycard/myfolder/filename.png
Sencha docs
Ext.device.filesystem.Cordova
Ext.device.filesystem.FileEntry
If you are using sencha touch 2.2 or below only change is instead of using sencha class you need to directly use phonegap api.
For reading file system & File download follow phonegap documentation.
Sencha basically operates over HTML, CSS & JS. Rather than doing this using Sencha just implement it similar to how you would do it in HTML then integrate into your application.
Eg: Homework
Try this
document.location= url;
Try the following code it may help you.
var newWindow = window.open('filepath', '_self'); //were filepath is the path of file with extension.