show audio or video controller in dart - dart

I want to create a audio or video controller, but my current code only plays the content, nothing is shown to control it in my browser
#import ('dart:html');
void main () {
AudioElement audio = new AudioElement();
audio.src="http://slides.html5rocks.com/src/rushus-modal_blues.mp3";
audio.autoplay=true;
window.document.body.nodes.add(audio);
}
So how do you get Dart to show a controller for audio/video ?

The controls for audio/video are disabled by default. You will need to enable them
audio.controls = true;
should do the trick.
Alternativly you can also build the audio source and controls settings from scractch, the following examples shows this and have been tested sucessfully with dart2js
var audioSource = new SourceElement();
audioSource.src = "http://slides.html5rocks.com/src/rushus-modal_blues.mp3";
audioSource.type = "audio/mp3";
var audio = new AudioElement();
audio.attributes["controls"] = "controls";
audio.nodes.add(audioSource);
window.document.body.nodes.add(audio);
There is more info on controlling audio here and video here

Related

audioplayer playing inconsistent / weird audio (url mp3 link) result in flutter

following the instructions from:
https://codingwithjoe.com/playing-audio-from-the-web-and-http/ (using his example and AudioProvider class)
I have been using:
audioplayer: ^0.8.1
audioplayer_web: ^0.7.1
to play audio from https link.
The problem it has some weird inconsistent effect.
- after playing few audio, it keeps on playing the same audio eventhough new url is loaded
- after playing few audio, the sound is weird like some part is cut with other audio.
What is a good audio player that accepts url link for flutter that can produce a consistent result ?
the provided audioplayer from your example works great and has good features. From what you are describing for me it seems like you're not closing the session when you play a sound. It seems like you are stacking the sounds which causes weird sounds.
You have to close the instance then. even though the article is outdated (march 2018) the audioplayer has developed further. check their offical guide here:
https://pub.dev/packages/audioplayer
This is version audioplayer 0.8.1 not 3.0 or something..
Example from docs:
Instantiate an AudioPlayer instance
//...
AudioPlayer audioPlugin = AudioPlayer();
//...
Player controls:
audioPlayer.play(url);
audioPlayer.pause();
audioPlayer.stop();
status and current position:
//...
_positionSubscription = audioPlayer.onAudioPositionChanged.listen(
(p) => setState(() => position = p)
);
_audioPlayerStateSubscription = audioPlayer.onPlayerStateChanged.listen((s) {
if (s == AudioPlayerState.PLAYING) {
setState(() => duration = audioPlayer.duration);
} else if (s == AudioPlayerState.STOPPED) {
onComplete();
setState(() {
position = duration;
});
}
}, onError: (msg) {
setState(() {
playerState = PlayerState.stopped;
duration = new Duration(seconds: 0);
position = new Duration(seconds: 0);
});
});
Like I said most of the audio plugins are running in singleton mode with instances. To provide getting weird effects you have to load the next song in the same instance, don't open another new instance, and you wont get any weird effects.
If you want to switch to a different audio player another great one which I used in an app project is the following:
https://pub.dev/packages/audio_manager#-readme-tab-
Hope it helps.

iOS How to trigger video to keep playing after exiting fullscreen?

I'm building a website that plays video in iOS. I have a fullscreen button working in iOS however the video pauses when exiting fullscreen. Does anyone know a way to either force the video to continue to play upon exiting fullscreen or how to set up a listener that triggers the video to autoplay upon exiting fullscreen?
here is my code:
<script>
var video = document.getElementById('tv'),
play = document.getElementById('fullscreenbutton'),
time;
video.addEventListener('webkitbeginfullscreen', function() {
play.innerText = '';
window.clearInterval(time);
});
video.addEventListener('webkitendfullscreen', function() {
tv.autoplay();
});
play.addEventListener('touchstart', function() {
time = window.setInterval(function() {
try {
video.webkitEnterFullscreen();
}
catch(e) {}
}, 250);
play.innerText = 'loading ...';
tv.play();
});
</script>
'''
You can use WKScriptMessageHandler in your iOS app when a button to exit fullscreen mode is tapped then resume your video player.
Here is a workaround on how I would handle this situation.
Native iOS + JavaScript
1 Step: Website front end part
When exit full screen button is tapped on your website emit an event give it a unique name something like "exitFullScreenEvent"
2 Step: iOS App
import WebKit
ViewController: WKScriptMessageHandler {
// Helper method to set configurations for your webView in iOS
func configureWebView() {
///Add the script message handler into the content controller.
let contentController = WKUserContentController()
/// Give it the same name as on the web front-end part
contentController.add(self, name: "exitFullScreenEvent")
let config = WKWebViewConfiguration()
config.userContentController = contentController
/// Most important, when initilizing your web view pass the configuration above
let webView = WKWebView(frame: .zero, configuration: config)
// Layout/add constraints to your webView
// .....
}
// Delegate method to listen an event emitted from your website
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
// TODO: - Resume/ Play your video
}
}
Pure Website (Javascript only)
For website only which runs in pure Javascript without any iOS related components and on Safari browser you might want to check this webkitjs displayingfullscreen
I Haven't used it before but it worth reading the doc.
But another work around without putting lots of effort is to compare your video player's screen size with the browsers window size ie.. check if browser is full screen if so get the full screen width if it's the same with your video player's size then video is in full screen.

AvPlayer and AirPlay not working quite well

I am coding a video player with Xamarin, AVPlayer and AvPlayerViewController. My code supports AirPlay and configures AVPlayer according docs but is not working quite well. The following scenario seems to fail:
Play a video, send it to Apple TV.
Exit playback as it goes on the Apple TV
Try to resume playback from the current position. This leads to playback directly starting on the Apple TV but the seek which I do to resume from the last playback position kind of fails. What happens is that AvPlayerViewController UI shows that playback starts from the beginning while the Apple TV is playing back from the resume point. The AvPlayerViewController play/pause button is also wrong most of the time and is not reflecting the right play state.
I do the seek so I resume the video like this: wait ( by KVO ) for the avplayer status to become ready to play, seek and then play the video.
Note ... all this works just fine when player is not in airplay mode. Video resumes properly and UI is looking correct.
Code looks like this:
avItem = new AVPlayerItem(avAsset);
avPlayer = new AVPlayer(avItem)
{
AllowsExternalPlayback = true,
UsesExternalPlaybackWhileExternalScreenIsActive = true
};
avPlayerViewController = new AVPlayerViewController()
{
View =
{
ContentMode = UIViewContentMode.ScaleAspectFill,
AutoresizingMask = UIViewAutoresizing.All,
},
UpdatesNowPlayingInfoCenter = false,
Player = avPlayer
};
initialPlaybackTime = TimeSpan.FromSeconds(bookmarkTime);
AddChildViewController(avPlayerViewController);
View.AddSubview(avPlayerViewController.View);
avPlayerViewController.DidMoveToParentViewController(this);
avItem.AddObserver(this, new NSString("status"), NSKeyValueObservingOptions.Initial, IntPtr.Zero);
public override async void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context)
{
if (Equals(ofObject, avItem) && keyPath.Equals((NSString)"status"))
{
if (!initialPlaybackTimeSet && (avPlayer.Status == AVPlayerStatus.ReadyToPlay))
{
await avPlayer.SeekAsync(CMTime.FromSeconds(initialPlaybackTime.TotalSeconds, avPlayer.CurrentItem.Asset.Duration.TimeScale));
avPlayer.Play();
initialPlaybackTimeSet = true;
}
}
}

Web Audio API not playing sound sample on device, but works in browser

I have an Ionic app that is a metronome. Using Web Audio API I have made everything work using the oscillator feature, but when switching to use a wav file no audio is playing on a real device (iPhone).
When testing in the browser using Ionic Serve (chrome) the audio plays fine.
Here is what I have:
function snare(e) {
var audioSource = 'assets/audio/snare1.wav';
var request = new XMLHttpRequest();
request.open('GET', audioSource, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
audioContext.decodeAudioData(request.response, function(theBuffer) {
buffer = theBuffer;
playSound(buffer);
});
}
request.send();
}
function playSound(buffer) {
var source = audioContext.createBufferSource();
source.buffer = buffer;
source.connect(audioContext.destination);
source.start(0);
}
The audio sample is in www/assets/audio.
Any ideas where this could be going wrong?
I believe iOS devices require a user-gesture of some sort to allow playing of audio.
It's July 2017, iOS 10.3.2 and we're still finding this issue on Safari on iPhones. Interestingly Safari on a MacBook is fine.
#Raymond Toy's general observation still appears to be true. But #padenot's approach (via https://gist.github.com/laziel/7aefabe99ee57b16081c) did not work for me in a situation where I wanted to play a sound in response to some external event/trigger.
Using the original poster's code, I've had some success with this
var buffer; // added to make it work with OP's code
// keep the original function snare()
function playSound() { // dropped the argument for simplicity.
var source = audioContext.createBufferSource();
source.buffer = buffer;
source.connect(audioContext.destination);
source.start(0);
}
function triggerSound() {
function playSoundIos(event) {
document.removeEventListener('touchstart', playSoundIos);
playSound();
}
if (/iPad|iPhone/.test(navigator.userAgent)) {
document.addEventListener('touchstart', playSoundIos);
}
else { // Android etc. or Safari, but not on iPhone
playSound();
}
}
Now calling triggerSound() will produce the sound immediately on Android and will produce the sound on iOS after the browser page has been touched.
Still not ideal, but better than no sound at all...
I had a similar issue in current iOS (15). I tried to play base64 encoded binary data which worked in all browsers, but not on iOS.
Finally reordering of the statements solved my issue:
let buffer = Uint8Array.from(atob(base64), c => c.charCodeAt(0));
let context = new AudioContext();
// these lines were within "play()" before
audioSource = context.createBufferSource();
audioSource.connect(context.destination);
audioSource.start(0);
// ---
context.decodeAudioData(buffer.buffer, play, (e) => {
console.warn("error decoding audio", e)
});
function play(audioBuffer) {
audioSource.buffer = audioBuffer;
}
Also see this commit in my project.
I assume that calling audioSource.start(0) within the play() method was somehow too late because it's within a callback after context.decodeAudioData() and therefore maybe "too far away" from a user interaction for the standards of iOS.

iOS app freezes, not crashing when loading video in webview

I have an iPad app developed using a 3rd party tool called OpenPlug which converts AS3 to C++ and from there on exports to iOS. (Just wanted to note this is not a "native" app using Obj-C in XCode written by me, I wrote AS3)
Now I have this iPad application which displays pictures and video in a slideshow. For the video I'm using a WebView which loads a HTML page where I change the src property of the video object to the location of the video file which was downloaded to my application storage. This is working fine except that the application freezes when it is running for a few hours (3-6).
I searched for this problem and tried the solution in iOS Safari memory leak when loading/unloading HTML5 <video> but that does not seem to change anything for me.
Since the application freezes (right before the HTML page needs to load a video) and does not crash what does that mean? Do I need to destroy the video object? First I was creating a new WebView for each video but now I'm reusing the webview and just changing the src property but that also does not help me.
Can anyone shed some light on this? OpenPlug has discontinued it service and does not offer any support anymore but nevertheless I think it is more of a webview/video problem on iPad (?)
Important to note: The application is freezing but my iPad is not. The application does not generate a crash report and does not execute any code anymore (also no traces). When I push the Home button on my iPad and press the app icon then the application is restarted.
Here is the code of my HTML page which is refreshed every time a new video needs to start (webview.location = ...)
<html>
<head>
<script>
function videoEndedHandler(){
var video = document.getElementById("videoPlayer");
video.src = "";
video.load();
window.location.hash = "ended";
}
function videoErrorHandler(){
window.location.hash = "error";
var video = document.getElementById("videoPlayer");
video.src = "";
video.load();
}
var loop;
function setup(){
var video = document.getElementById("videoPlayer");
video.addEventListener("error", videoErrorHandler,false);
video.addEventListener("ended", videoEndedHandler,false);
video.load();
video.play();
startHashLoop();
}
function startHashLoop(){
if(window.location.hash == "#touched"){
setAsPaused();
}
if(window.location.hash == "#paused"){
//check image
testImage("shouldResume.png?nocache=" + Math.random());
}
if(window.location.hash == "#resume"){
var video = document.getElementById("videoPlayer");
video.play();
}
loop = setTimeout(hashLoop,500);
}
function testImage(url) {
var img = new Image;
img.addEventListener("load",isGood);
img.addEventListener("error",isBad);
img.src = url;
}
function isGood() {
window.location.hash = "resume";
}
function isBad() {
//alert("Image does not exist");
}
function hashLoop(){
startHashLoop();
}
function setAsTouched(){
window.location.hash = "touched";
}
function setAsPaused(){
var video = document.getElementById("videoPlayer");
video.pause();
window.location.hash = "paused";
}
</script>
</head>
<body onload="setup();" style="background-color:#000000;">
<video id="videoPlayer" style="top:0;left:0;position:absolute;" width="100%" height="100%" preload="auto" src="##VIDEO_URL##" autoplay="autoplay" webkit-playsinline />
</body>
</html>
It would be helpful if you'd post your entire code, but I think it's freezing because you're loading a video from web in your main thread, which is also responsible for redrawing UI. By loading a large video inside your thread, your UI freezes as well.
I would recommend moving the code that does video loading into a separate thread (use blocks if you're on iOS5).

Resources