Convert PHAsset/AVAsset to mp4 video in Nativescript app - javascript

I use the nativescript-imagepicker-plugin for a filepicker.
This returns a PHAsset.
I have to copy it to a temporary directory to upload it.
Im new in iOS, so I tried a bit:
const options = PHVideoRequestOptions.new();
options.version = PHVideoRequestOptionsVersion.Current;
PHImageManager
.defaultManager()
.requestAVAssetForVideoOptionsResultHandler(
phAsset
, options
, (avAsset, audioMix, info) => {
try {
const tempFilePath = path.join(tempFolderPath, `${Date.now()}.mp4`);
const targetURL = NSURL.fileURLWithPath(tempFilePath);
const exportSession = AVAssetExportSession.alloc(avAsset, AVAssetExportPresetPassthrough);
exportSession.outputUrl = targetURL;
exportSession.outputFileType = AVFileTypeMPEG4;
exportSession.exportAsynchronouslyWithCompletionHandler(() => {
console.log(exportSession.status);
});
}
catch (e) {
console.log(e);
}
}
);
My code crashes without error, so I don't know where to start to debug.
I want a MP4, to show it in web too.
At the end I need a string (path) to a mp4 file to upload id with nativescript-background-http.

Your syntax seems to be wrong
const exportSession = AVAssetExportSession.alloc().initWithAssetPresetName(avAsset, AVAssetExportPresetPassthrough);
exportSession.outputURL = targetURL;

Related

JavaScript Recorded audio has unknown duration

okay so I successfully created a structure to record and download audio. But the problem is the final downloaded file has unknown duration. is there any way to work around that??
Here is my code (it's in Typescript)
let recorder: MediaRecorder,
dataArray: Blob[]
async function InitializeAudio(): Promise<void> {
let audioIN = { audio: true }
try {
const mediastremObj = await navigator.mediaDevices.getUserMedia(audioIN)
const mediaRecorder = new MediaRecorder(mediastremObj)
recorder = mediaRecorder
recorder.ondataavailable = (ev)=>{
dataArray.push(ev.data)
}
recorder.onstop = (ev) => {
const downloadTag = document.querySelector('#file-download') as HTMLAnchorElement
const audioFile = new Blob(dataArray, {'type': 'audio/mp3;'})
const url = window.URL.createObjectURL(audioFile)
downloadTag.href = url
downloadTag.download = `my-${Date.now()}-audio.mp3`
downloadTag.click()
window.URL.revokeObjectURL(url)
dataArray = []
}
} catch (e) {
throw new Error(e)
}
}
okay so after weeks of searching and researching, i found out that the media recorder API can only record in mime types supported by the browser. in chrome browser the only supported mime type is audio/webm, and the generated Blob can't be converted to any other mimetype. i was able to find a lasting solution using wavesufer & lamejs libraries.
link to them πŸ‘‡πŸ‘‡
https://www.npmjs.com/package/wavesurfer.js?activeTab=readme
https://www.npmjs.com/package/lamejs
you might have an error using the lame js library, so here is a link to a refactored fork of the lame js projectπŸ‘‡πŸ‘‡
https://www.npmjs.com/package/lamejstmp

Can not get AEC model Data in Autodesk Forge

i try to activate Revit Levels and 2D Minimap extension in autodesk forge viewer, but can not get AEC Model Data. I got this worning`
i tried to get AEC data with this code
const url = window.location.search;
console.log(url);
const svf_path = `${url.replace("?", "/storage/").replace(/%20/g, " ")}`;
Autodesk.Viewing.endpoint.getItemApi = (endpoint, derivativeUrn, api) => {
return svf_path;
};
Autodesk.Viewing.Initializer(options, async () => {
const paths = svf_path.split("/");
const [dest, svf_dir] = [paths[2], paths[3]];
const url = `/api/viewer/dest/${dest}/svf/${svf_dir}/manifest`;
const response = await fetch(url);
const manifest = await response.json();
const init_div = document.getElementById("init_div");
viewer = new Autodesk.Viewing.GuiViewer3D(init_div, config3d);
const viewerDocument = new Autodesk.Viewing.Document(manifest);
const viewable = viewerDocument.getRoot().getDefaultGeometry();
viewer.start();
await viewerDocument.downloadAecModelData();
viewer.loadDocumentNode(viewerDocument, viewable)
.then(function (result) {
Autodesk.Viewing.Document.getAecModelData(viewable);
})
});
wats wrong in my code?
The warning comes from the BubbleNode.prototype.getAecModelData method. You are not calling it in your code but it's possible that it's being called by the LevelsExtension itself. Try configuring the extension so that it doesn't detect the AEC data automatically by passing in { autoDetectAecModelData: false } as the extension options.
Btw. to debug the issue on your side, you can also try getting the non-minified version of viewer3D.js, put a breakpoint to where the warning is being logged, and see the call stack when the breakpoint is hit.

Downloading an Azure Storage Blob using pure JavaScript and Azure-Storage-Js

I'm trying to do this with just pure Javascript and the SDK. I am not using Node.js. I'm converting my application from v2 to v10 of the SDK azure-storage-js-v10
The azure-storage.blob.js bundled file is compatible with UMD
standard, if no module system is found, following global variable
will be exported: azblob
My code is here:
const serviceURL = new azblob.ServiceURL(`https://${account}.blob.core.windows.net${accountSas}`, pipeline);
const containerName = "container";
const containerURL = azblob.ContainerURL.fromServiceURL(serviceURL, containerName);
const blobURL = azblob.BlobURL.fromContainerURL(containerURL, blobName);
const downloadBlobResponse = await blobURL.download(azblob.Aborter.none, 0);
The downloadBlobResponse looks like this:
downloadBlobResponse
Using v10, how can I convert the downloadBlobResponse into a new blob so it can be used in the FileSaver saveAs() function?
In azure-storage-js-v2 this code worked on smaller files:
let readStream = blobService.createReadStream(containerName, blobName, (err, res) => {
if (error) {
// Handle read blob error
}
});
// Use event listener to receive data
readStream.on('data', data => {
// Uint8Array retrieved
// Convert the array back into a blob
var newBlob = new Blob([new Uint8Array(data)]);
// Saves file to the user's downloads directory
saveAs(newBlob, blobName); // FileSaver.js
});
I've tried everything to get v10 working, any help would be greatly appreciated.
Thanks,
You need to get the body by await blobBody.
downloadBlobResponse = await blobURL.download(azblob.Aborter.none, 0);
// data is a browser Blob type
const data = await downloadBlobResponse.blobBody;
Thanx Mike Coop and Xiaoning Liu!
I was busy making a Vuejs plugin to download blobs from a storage account. Thanx to you, I was able to make this work.
var FileSaver = require('file-saver');
const { BlobServiceClient } = require("#azure/storage-blob");
const downloadButton = document.getElementById("download-button");
const downloadFiles = async() => {
try {
if (fileList.selectedOptions.length > 0) {
reportStatus("Downloading files...");
for await (const option of fileList.selectedOptions) {
var blobName = option.text;
const account = '<account name>';
const sas = '<blob sas token>';
const containerName = '< container name>';
const blobServiceClient = new BlobServiceClient(`https://${account}.blob.core.windows.net${sas}`);
const containerClient = blobServiceClient.getContainerClient(containerName);
const blobClient = containerClient.getBlobClient(blobName);
const downloadBlockBlobResponse = await blobClient.download(blobName, 0, undefined);
const data = await downloadBlockBlobResponse.blobBody;
// Saves file to the user's downloads directory
FileSaver.saveAs(data, blobName); // FileSaver.js
}
reportStatus("Done.");
listFiles();
} else {
reportStatus("No files selected.");
}
} catch (error) {
reportStatus(error.message);
}
};
downloadButton.addEventListener("click", downloadFiles);
Thanks Xiaoning Liu!
I'm still learning about async javascript functions and promises. Guess I was just missing another "await". I saw that "downloadBlobResponse.blobBody" was a promise and also a blob type, but, I couldn't figure out why it wouldn't convert to a new blob. I kept getting the "Iterator getter is not callable" error.
Here's my final working solution:
// Create a BlobURL
const blobURL = azblob.BlobURL.fromContainerURL(containerURL, blobName);
// Download blob
downloadBlobResponse = await blobURL.download(azblob.Aborter.none, 0);
// In browsers, get downloaded data by accessing downloadBlockBlobResponse.blobBody
const data = await downloadBlobResponse.blobBody;
// Saves file to the user's downloads directory
saveAs(data, blobName); // FileSaver.js

how to decode qr code that contains base 64 png in react js

I have been trying to decode this qr code that has json data.
In online tools its working example https://www.onlinebarcodereader.com/. It reads the data.
I am trying programmatically
here is my code
handleFileChange(event) {
const {target} = event;
const {files} = target;
if (files && files[0]) {
const reader = new FileReader();
// reader.onloadstart = () => this.setState({loading: true});
reader.onload = async event => {
this.setState({
data: event.target.result,
loading: false
});
// const img = document.getElementById('img');
console.log(event.target.result);
let result;
try {
var qr = new QrCode();
// set the callback that receives the decoded content as the tasks is async
qr.callback = function(decodedDATA){
alert(decodedDATA);
};
// event.target.result is
//data:image/png;base64,iVBORw0KGgoAAAANSU...
qr.decode(event.target.result);
} catch (err) {
console.log(err);
}
console.log(result);
};
reader.readAsDataURL(files[0]);
}
}
<input
id="img"
type="file"
accept="image/*"
onChange={this.handleFileChange}
/>
I have used this library https://www.npmjs.com/package/qrcode-reader
It has bug that cannot read data more than certain characters hence i am getting error.
I have also tried to use zxing library but i am using server side rendering getting error window is undefined. There are lot of configurations need to be done in webpack but i am not aware of those. I am looking for simple fix for this.
Can any one please help me out with the working library.
Found the solution with this library qrcode-decoder.
In my code
import QrcodeDecoder from 'qrcode-decoder';
const qr = new QrcodeDecoder();
const result = await qr.decodeFromImage(event.target.result);

How to get the number of pages of a .PDF uploaded by user?

I have a file input, and before "uploading" i need to calculate the number of pages of that .pdf in JAVASCRIPT (eg. JQuery...)
In case you use pdf.js you may reference an example on github ('.../examples/node/getinfo.js') with following code that prints number of pages in a pdf file.
const pdfjsLib = require('pdfjs-dist');
...
pdfjsLib.getDocument(pdfPath).then(function (doc) {
var numPages = doc.numPages;
console.log('# Document Loaded');
console.log('Number of Pages: ' + numPages);
})
and a pure javascript solution:
var input = document.getElementById("files");
var reader = new FileReader();
reader.readAsBinaryString(input.files[0]);
reader.onloadend = function(){
var count = reader.result.match(/\/Type[\s]*\/Page[^s]/g).length;
console.log('Number of Pages:',count );
}
As has been stated in the other answers, something like pdf.js is be what you are looking for. I've taken a look at the API and it does include a numPages() function to return the total number of pages. It also seems to count pages for me when viewing the demo page from Mozilla.
It depends if you are able to use modern browsers and experimental technology for your solution. pdf.js is very impressive, but it is still experimental according to the github page .
If you are able to count the pages on the server after uploading, then you should look at pdftools or similar.
Something like pdftools --countpages is what you are looking for
I think the API has changed a little since Tracker1 posted an answer. I tried Tracker1's code and saw this error:
Uncaught TypeError: pdfjsLib.getDocument(...).then is not a function
A small change fixes it:
const pdfjsLib = require('pdfjs-dist');
...
pdfjsLib.getDocument(pdfPath).promise.then(function (doc) {
var numPages = doc.numPages;
console.log('# Document Loaded');
console.log('Number of Pages: ' + numPages);
}
In typescript class using Pdf-lib I use the following.
// getPAGE COUNT:
async getPageCount(formUrl: any): Promise<number>{
const LogPdfFields = [] as any[];
const formPdfBytes = await fetch(formUrl).then((res) => res.arrayBuffer());
const pdfDoc = await PDFDocument.load(formPdfBytes);
const pageCount = pdfDoc.getPageCount();
return pageCount;
}
Call as a promise
You could also use pdf-lib.
You will need to read the file from the input field and then make use of pdf-lib to get the number of pages. The code would be like this:
import { PDFDocument } from 'pdf-lib';
...
const readFile = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
reader.readAsArrayBuffer(file);
});
}
const getNumPages =async (file) => {
const arrayBuffer = await readFile(file);
const pdf = await PDFDocument.load(arrayBuffer);
return pdf.getPages();
}
And then just get the number of pages of the attached file with:
const numPages = await getNumPages(input.files[0]);
being input the variable which stores the reference to the DOM element of the file input.

Categories