I am trying to use preloadjs to load mp3 file. I also use HTMLAudioPlugin in Soundjs, but when I want to get the audiodom as use getResult function, it doesn't work in ios but not in chrome.
preloadManifest = [{src: "bgm.mp3", id: 'bgm', type:'createjs.AbstractLoader.SOUND'}]
createjs.Sound.registerPlugins([createjs.HTMLAudioPlugin]);
loader = new createjs.LoadQueue(true, null, true);
loader.addEventListener('complete',function () {
loader.getResult('bgm') // undefined in ios
});
Related
I've downloaded a video to disk but it won't initialise using Video Player (https://pub.dev/packages/video_player).
final future = Downloader.shared
.getVideoPathFor(
url: url,
themeName: themeName,
)
.then(
(value) {
dLog('file path: $value');
final file = File(value);
final videoController = VideoPlayerController.file(file);
return videoController.initialize().then(
(value) {
dLog('video controller initialized');
return videoController;
},
);
},
);
It downloads the file fine and the file path becomes something like:
Application/9E6FD935-A424-4C1E-99CC-D5834448E45E/Library/Caches/videos/Clean water/clean_water_video.mp4
So I know the file exists and I can see it in Finder if I run this on Simulator.
If I use VideoController.contentUri() then it appears to work but it tells me I'm not allowed to use that on iOS and I can only use it on Android.
I know I can use VideoController.network() but I can't keep downloading the same video over and over across multiple screens like this.
What am I doing wrong?
Even when I do load the video like this (which I got from this video: https://youtu.be/uz4xRnE-UIw?t=596):
final filePath =
"<path>/Caches/videos/Clean water/clean_water_video.mp4";
final file = File(filePath);
controller = VideoPlayerController.file(file)
..addListener(() {
setState(() {});
})
..setLooping(true)
..initialize().then((value) {
controller.play();
});
the initialise never happens.
It turns out that it can't load a file if folders have spaces in the name.
I am using nativescript-mediafilepicker as means of choosing a file, and this can read external storage successfully (I have downloaded a PDF to the 'downloads' folder on iOS and I am able to pick it.) I then try to load the file using the file system module from nativescript library, and this fails because it is listed as NativeScript encountered a fatal error: Uncaught Error: You can’t save the file “com.xxxxxx” because the volume is read only. This doesn't make sense as I am trying to read anyway - I don't understand where the saving part is from. The error comes from fileSystemModule.File.fromPath() line.
Something to note that file['file'] is file:///Users/adair/Library/Developer/CoreSimulator/Devices/82F397CE-B0B3-4ADD-AD52-805265C7AC49/data/Containers/Data/Application/7B47A8BD-6DBA-42CF-8792-38A8C5E61174/tmp/com.xxxxxx/test.pdf
Is the file automatically being pulled to an application specific directory after this media picker?
getFiles() {
let extensions = [];
if (app.ios) {
extensions = [kUTTypePDF]; // you can get more types from here: https://developer.apple.com/documentation/mobilecoreservices/uttype
} else {
extensions = ["pdf"];
}
const mediaFilePicker = new Mediafilepicker();
const filePickerOptions = {
android: {
extensions,
maxNumberFiles: 1,
},
ios: {
extensions,
maxNumberFiles: 1,
},
};
masterPermissions
.requestPermissions([masterPermissions.PERMISSIONS.READ_EXTERNAL_STORAGE,masterPermissions.PERMISSIONS.WRITE_EXTERNAL_STORAGE])
.then((fulfilled) => {
console.log(fulfilled);
mediaFilePicker.openFilePicker(filePickerOptions);
mediaFilePicker.on("getFiles", function (res) {
let results = res.object.get("results");
let file = results[0];
console.dir(file);
let fileObject = fileSystemModule.File.fromPath(file["file"]);
console.log(fileObject);
});
mediaFilePicker.on("error", function (res) {
let msg = res.object.get("msg");
console.log(msg);
});
mediaFilePicker.on("cancel", function (res) {
let msg = res.object.get("msg");
console.log(msg);
});
})
.catch((e) => {
console.log(e);
});
},
The issue I have experienced is resultant of the expectation of File.fromPath and what is returned by the file picker. File picker is returning a "file://path" URI, and File.fromPath is expecting a string of just "path".
Simply using the following instead is enough.
let fileObject = fileSystemModule.File.fromPath(file["file"].replace("file://","");
I am developing an iOS app with react-native. I wanted to use MediaRecorder which is still in 'experimental' phase. I turned it on in advanced Safari settings but when I try to use it in my app:
var mediaRecorder = new MediaRecorder(stream)
I get this error:
ReferenceError: Can't find variable: MediaRecorder
This feature works well in safari, but I can't get it to work in my app. Is there a way to turn it on in Xcode/real-native settings?
EDIT:
Here is the larger section of my code. I use react-native-webrtc that provides mediaDevices component. I do capture the stream, the problem I have is with MediaRecorder. I know that MediaRecorder works in safari browser, the question I have is if it can be used in a mobile iOS app and if so, how to enable it.
import {
RTCPeerConnection,
RTCIceCandidate,
RTCSessionDescription,
RTCView,
MediaStream,
MediaStreamTrack,
mediaDevices,
registerGlobals
} from 'react-native-webrtc';
var mediaRecorder;
const pc_config = {
"iceServers": [
{
urls: 'stun:stun.l.google.com:19302'
}
]
}
var pc = new RTCPeerConnection(pc_config)
const success = (stream) => {
mediaRecorder = new MediaRecorder(stream) //this line throws the error
pc.addStream(stream)
}
const failure = (e) => {
console.log('getUserMedia Error: ', e)
}
const constraints = {
audio: true,
video: {
mandatory: {
minWidth: 200,
minHeight: 200*(16/9),
minFrameRate: 24
},
facingMode: "user"
}
}
mediaDevices.getUserMedia(constraints)
.then(success)
.catch(failure);
The MediaRecorder constructor syntax is
var mediaRecorder = new MediaRecorder(stream[, options]);
as in
navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
var mediaRecorder = new MediaRecorder(stream);
}
When running only the following line in the Safari 13 console with Experimental MediaRecorder activated:
var mediaRecorder = new MediaRecorder(stream)
I get the following (expected) output:
ReferenceError: Can't find variable: stream
I am recording audio, sending it as a blob to a nodejs server. The nodejs server then sends it to all connected users that are not currently recording.
Sending the blob:
mediaRecorder.onstop = function(e) {
var blob = new Blob(this.chunks, { 'type' : 'audio/ogg; codecs=opus' });
socket.emit('radio', blob);
};
Server receiving the blob:
socket.on('radio', function(blob) {
socket.broadcast.emit('voice', blob);
});
Listener receiving the blob:
socket.on('voice', function(arrayBuffer) {
var blob = new Blob([arrayBuffer], { 'type' : 'audio/ogg; codecs=opus' });
var audio = document.getElementById('audio');
audio.src = window.URL.createObjectURL(blob);
audio.play();
});
This works in all browsers/devices except safari and any ios device. Taking it further with safari's inspector I found this:
Does safari require something else in its headers for blob objects to be interpreted properly? I've researched accepted audio types, tried aac/mp3/ogg without any success. Upon reading further I've heard references to the fact that there is a bug with streaming blob audio/video data in safari and IOS though I'm not too clear any the details.
Guidance in the rite direction would be very helpful!
EDIT: It looks like this line audio.src = window.URL.createObjectURL(blob); in the receiving blob is what is causing the blob errors (image i linked)
EDIT 2: I tried to see if using another format other than blob would work, opting for base64 encoded string. Looks like this works on all devices and browsers except for IOS and Safari. I'm getting the impression it has something to do with how IOS interprets/loads the data...
For me the solution was to insert a source element into the audio element, and use the sourceElement.src attribute to refer to the blob. I didn't even need to attach the audio-element to the DOM. Example below, hope it helps someone.
var audioElement = document.createElement('audio')
var sourceElement = document.createElement('source')
audioElement.appendChild(sourceElement)
sourceElement.src = '<your blob url>'
sourceElement.type = 'audio/mp3' // or whatever
audioElement.load()
audioElement.play()
I haven't been able to find a solution using an audio element, however the Web Audio Api seems to do the trick: https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API
var audioContext = new (window.AudioContext || window.webkitAudioContext);
socket.on('voice', function(arrayBuffer) {
audioContext.decodeAudioData(arrayBuffer, audioData => {
var source = audioContext.createBufferSource();
source.buffer = audioData;
source.connect(audioContext.destination);
source.start()
});
You may still have an issue on iOS as any audio/video must be triggered by a user action.
I had a similar problem this week. I was recording the audio on Safari and the audio blob was being generated just fine. But when I tried to send the blob to server, no data was getting there. The solution bellow reads the blob with File Reader to convert it to base64, and afterwards send it to server. Here is what worked for me:
const reader = new FileReader();
reader.readAsDataURL(audioBlob);
reader.onloadend = () => {
const base64data = reader.result;
const audioName = uuid.v4() + '.mp3';
this.http.post(this.app.cloudStorageEndpoint + '/audios/local?audioName=' + audioName, base64data , header).subscribe(
res => { resolve(audioName); },
err => { reject(err); }
);
};
I've tested with Safari 12 on both iPad and iPhone and it worked fine.
I'm using the cordova screenshot plugin : https://github.com/gitawego/cordova-screenshot to take a screenshot in my iPhone using this code :
navigator.screenshot.save(function (error, res) {
if (error) {
console.log('Screenshot error');
console.error(error);
} else {
console.log('screenshot ok', res.filePath);
}
}, 'jpg', 50, 'project-X-result');
It seems to work (i have no error) but I can't find the screenshot in the Photos Library. Is it possible to save it in this library?
How should I do? Using another plugin to move the file? (where should it be moved exactly?) Editing the plugin to save it directly in the library? (where should it be saved exactly?)
I just ran through the same problem. It took several days but I figured out how to do it.
It does involve another plugin Canvas2Image plugin. I didn't think it would work, but I was desperate and it did work in the end. Here's how I did it.
If you are getting the console.log for screenshot ok, then you are in good shape. The next thing you will need to do is install Canvas2Image with your CLI like so:
cordova plugin add https://github.com/devgeeks/Canvas2ImagePlugin.git
(or replace 'cordova' with 'phonegap' if you use that instead.)
Next, you will need to add a function (in this case saveImageToPhone()) that calls the plugin you just added to your project. This function will be called from your navigator.screenshot.save() function you already have. We will add that function call to your screenshot.save success block, right after the console.log line.
The key here is using that filePath property that we get back in the success block; That's our absolute path to the image we just saved to the temp folder in iOS. We will simply pass that path to the second function and let it do its work.
Here's those two functions from my code:
function saveScreen(){
navigator.screenshot.save(function(error,res){
if(error){
console.error(error);
}else{
console.log('ok',res.filePath);
var MEsuccess = function(msg){
console.info(msg);
} ;
var MEerror = function(err){
console.error(err);
};
saveImageToPhone(res.filePath, MEsuccess, MEerror);
}
},'jpg',90);
}
function saveImageToPhone(url, success, error) {
var canvas, context, imageDataUrl, imageData;
var img = new Image();
img.onload = function() {
canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
try {
imageDataUrl = canvas.toDataURL('image/jpeg', 1.0);
imageData = imageDataUrl.replace(/data:image\/jpeg;base64,/, '');
cordova.exec(
success,
error,
'Canvas2ImagePlugin',
'saveImageDataToLibrary',
[imageData]
);
}
catch(e) {
error(e.message);
}
};
try {
img.src = url;
}
catch(e) {
error(e.message);
}
}
Now just call the first function from wherever you wish.
If it works, you'll get a console.log right after your filePath readout that says
IMAGE SAVED!
Be careful, you might overwrite the same screenshot if you use a name as a screenshot.save parameter (after your jpg and quality parameters). My app needs to save different screenshots and have them all available later; by removing the name parameter and allowing the OS to name the file I was able to achieve just that.
I hope that helps you out, I know it caused me a lot of trouble...