Issue with enabling Picture-in-Picture feature on iOS Progressive Web Apps

My goal is to enable Picture-in-Picture (PiP) on an HTML video by using the code below:

await videoElement.requestPictureInPicture().catch((error) => 
    alert(`PiP failed, ${error}`);
);

While this code works perfectly in Safari, I encountered an issue when adding the website to the home screen with

"display": "standalone"
set in the manifest. The error message indicates that picture-in-picture is not supported and the built-in PiP control is missing from the video player.

I am curious as to why this discrepancy exists or if there is a workaround for it. I initially assumed that the PWA/standalone version utilizes the same browser/js engine as regular Safari, but it appears that might not be the case?

Answer №1

Update as of March 2021:

Regrettably, it appears that enabling PiP mode in PWAs is not currently supported due to the missing API in standalone mode.

After conducting some research and testing various methods, I discovered a workaround.

The only somewhat effective approach involves guiding users to load the video page within Safari by manipulating the scope parameter in your manifest file.

  1. Place your PWA in a subfolder like /pwa and set
    "scope": "/pwa"
  2. Create another subfolder for your Video pages like /videos

Whenever a user navigates to a video page, the PWA's scope is left, exiting fullscreen mode and prompting Safari to display its top and bottom bars. An icon in the bottom bar must be clicked to open Safari and enable PiP mode.

To streamline this process, you can include a custom PiP button in the video controls. If the user clicks it, check if the app is running in standalone mode with window.navigator.standalone. If it's false, request PiP otherwise exit the PWA's scope using the history API (history.pushState) while adding a query param like autopip=true. Display an overlay instructing the user to click the safari button in the bottom right corner.

A key limitation: There is no straightforward method to guide users back to your PWA from Safari.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to access a file within a project folder using JavaScript?

Currently, I am tackling a react project that involves dealing with a video file located in the public folder. In a specific scenario, I need to read this file and then send it over to the server as a file. I attempted the code snippet below but unfortunat ...

The Admob platform is displaying test ads, but my actual ads are not appearing

I'm currently using Admob to display Android ads in my app. Strangely, my actual ads are not appearing, but when I input the test code, it works perfectly fine. Interestingly, when I tested my ads in a different game, they displayed as intended. It&ap ...

Utilizing ionic-scroll for seamless movement and scrolling of a canvas element

I have set up a canvas element with a large image and I want to enable dragging using ionic-scroll. Following the provided example: <ion-scroll zooming="true" direction="xy" style="width: 500px; height: 500px"> <div style="width: 5000px; h ...

Optimal management using an image and an onClick event to trigger a JavaScript function

Which control stands out as the optimal choice for displaying images, executing JavaScript functions without postback, and possibly even changing images on hover? ...

Issue with the loading order of jQuery in Internet Explorer 9

My webpage heavily relies on jQuery for its functionality. While it works perfectly on most browsers, I am encountering issues specifically with IE9 due to the slow loading of JavaScript. The main problem lies in IE9 mistakenly thinking that JavaScript is ...

What is the best way to disable the functions doajax_red and doajax_blue when a radio button is checked?

Is there a way to halt the functions doajax_red and doajax_blue when a radio button is checked? Upon loading the page index.php, clicking the red button will display a loading image. If you check the BLUE radio button and then re-check the RED radio butt ...

Trouble with Installing Express

I have encountered an issue while trying to install express, despite following various solutions without success. Upon installation, I receive the message: npm WARN <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fb8c9e9988928f9 ...

Ensuring Accessibility in Vue using Jest-Axe: It is important for buttons to have clear and distinguishable text. Is there a way to include a button name or aria-label when the content is passed through a slot

I have been focusing on enhancing the accessibility of my project by incorporating ESLint rules from vuejs-accessibility and integrating Jest-Axe. During the accessibility tests for my button components, Jest-Axe highlighted that Buttons must have discern ...

What steps can I take to address the issue with the jquery dropdown?

I am struggling with implementing JavaScript functionality on my website. Specifically, I have a dropdown menu in the hamburger menu that is causing some issues. Whenever I click on the services option, the dropdown opens but quickly closes again. I'v ...

What is the best way to include a file attachment using a relative path in Nodemailer?

I am currently utilizing the html-pdf converter plugin to transform an HTML page into a PDF file. After conversion, this plugin automatically saves the PDF to the downloads folder. When I attempt to attach a PDF to a nodemailer email, my code looks someth ...

A method for automatically refreshing a webpage once it switches between specific resolutions

On my page www.redpeppermedia.in/tc24_beta/, it functions well at a resolution of over 980px. However, when the resolution is brought down to 768px, the CSS and media queries alter the layout. But upon refreshing the page at 768px, everything corrects itse ...

Efficiently perform complex nested grouping using the powerful array

Hi, I'm currently facing difficulties while attempting to utilize the array.reduce() function in order to achieve correct grouping for a specific scenario: Here is my original array: { { descriptionFunction: "Change", processDate: "201 ...

Form appears outside the modal window

I am facing an issue with my modal where the form inside is displaying outside of the modal itself. Despite trying to adjust the CSS display settings and switching to react-bootstrap from regular bootstrap, the problem persists. I am uncertain about what s ...

Implementing interactive dropdown menus to trigger specific actions

I have modified some code I found in a tutorial on creating hoverable dropdowns from W3. Instead of the default behavior where clicking on a link takes you to another page, I want to pass a value to a function when a user clicks. Below is a snippet of the ...

Is there a more efficient method to display and conceal multiple div elements with jQuery?

I am looking for an alternative method to use jQuery to show and hide divs. This code is specifically for testing purposes and includes a large number of divs that will make the code quite long once all are added. HTML Code <!DOCTYPE html> <html ...

What should I do to resolve the issue of ajax failing to update data randomly?

This script is designed to take the value entered into an HTML form and send it to the ../Resources/BugReport.php file. The data is then inserted into a database in that file, and the table in the ../Resources/BugDisplay.php file displays the information f ...

React: When component is suspended, the useEffect hook is not triggered

Exploring the world of react hooks and react suspense has led me to creating a custom hook called useApolloQuery. This hook is designed to fetch data and utilize a promise to wait until the data is loaded. My approach involves placing the data fetching lo ...

Creating unique sizes for each quad in Three.js using InstancedBufferGeometry and ShaderMaterial

I'm working on creating a visually dynamic scene filled with points of varying widths and heights. The challenge I'm facing is figuring out how to manipulate the vertices in the vertex shader to achieve customized sizes for each point. Here' ...

Is it possible to exchange code among several scripted Grafana dashboards?

I have developed a few customized dashboards for Grafana using scripts. Now, I am working on a new one and realizing that I have been duplicating utility functions across scripts. I believe it would be more efficient to follow proper programming practices ...

Issue with event listener not functioning properly with dynamically created content using AJAX (only using vanilla JavaScript

I used pure javascript AJAX to dynamically load content into the "test" div. However, when I try to click on a child div at index 6, an alert box is not being displayed as expected. How can I fix the issue with the click event not working? The gets functi ...