@@ -175,6 +175,8 @@ public extension YouTubePlayer.HTMLBuilder {
175175 width: 100%;
176176 height: 100%;
177177 }
178+
179+ /* CSS pour forcer le rendu software et permettre la capture */
178180 .player-container iframe,
179181 .player-container object,
180182 .player-container embed {
@@ -183,7 +185,25 @@ public extension YouTubePlayer.HTMLBuilder {
183185 left: 0;
184186 width: 100% !important;
185187 height: 100% !important;
188+ /* Forcer le rendu software pour la capture */
189+ -webkit-transform: translate3d(0, 0, 0) !important;
190+ transform: translate3d(0, 0, 0) !important;
191+ will-change: auto !important;
192+ backface-visibility: visible !important;
193+ -webkit-backface-visibility: visible !important;
186194 }
195+
196+ /* Styles pour tous les éléments vidéo */
197+ video {
198+ -webkit-transform: translate3d(0, 0, 0) !important;
199+ transform: translate3d(0, 0, 0) !important;
200+ will-change: auto !important;
201+ backface-visibility: visible !important;
202+ -webkit-backface-visibility: visible !important;
203+ opacity: 1 !important;
204+ visibility: visible !important;
205+ }
206+
187207 ::-webkit-scrollbar {
188208 display: none !important;
189209 }
@@ -193,14 +213,65 @@ public extension YouTubePlayer.HTMLBuilder {
193213 <div class= " player-container " >
194214 <div id= " \( htmlBuilder. youTubePlayerJavaScriptVariableName) " ></div>
195215 </div>
196-
216+
197217 <script src= " \( htmlBuilder. youTubePlayerIframeAPISourceURL) "
198218 onerror= " window.location.href=' \( htmlBuilder. youTubePlayerEventCallbackURLScheme) :// \( YouTubePlayer . Event. Name. iFrameApiFailedToLoad. rawValue) ' " >
199219 </script>
200-
220+
201221 <script>
202222 var \( htmlBuilder. youTubePlayerJavaScriptVariableName) ;
203223
224+ // Fonction pour optimiser les vidéos pour la capture
225+ function optimizeVideoForCapture() {
226+ const videos = document.querySelectorAll('video');
227+ videos.forEach(video => {
228+ video.style.transform = 'translate3d(0, 0, 0)';
229+ video.style.willChange = 'auto';
230+ video.style.backfaceVisibility = 'visible';
231+ video.style.webkitBackfaceVisibility = 'visible';
232+ video.style.opacity = '1';
233+ video.style.visibility = 'visible';
234+ });
235+
236+ const iframes = document.querySelectorAll('iframe');
237+ iframes.forEach(iframe => {
238+ iframe.style.transform = 'translate3d(0, 0, 0)';
239+ iframe.style.willChange = 'auto';
240+ iframe.style.backfaceVisibility = 'visible';
241+ iframe.style.webkitBackfaceVisibility = 'visible';
242+ });
243+ }
244+
245+ // Observer pour les nouveaux éléments vidéo ajoutés dynamiquement
246+ const observer = new MutationObserver(function(mutations) {
247+ mutations.forEach(function(mutation) {
248+ mutation.addedNodes.forEach(function(node) {
249+ if (node.nodeType === 1) { // ELEMENT_NODE
250+ const videos = node.querySelectorAll ? node.querySelectorAll('video') : [];
251+ const iframes = node.querySelectorAll ? node.querySelectorAll('iframe') : [];
252+
253+ [...videos, ...iframes].forEach(element => {
254+ element.style.transform = 'translate3d(0, 0, 0)';
255+ element.style.willChange = 'auto';
256+ element.style.backfaceVisibility = 'visible';
257+ element.style.webkitBackfaceVisibility = 'visible';
258+ if (element.tagName === 'VIDEO') {
259+ element.style.opacity = '1';
260+ element.style.visibility = 'visible';
261+ }
262+ });
263+
264+ if (node.tagName === 'VIDEO' || node.tagName === 'IFRAME') {
265+ node.style.transform = 'translate3d(0, 0, 0)';
266+ node.style.willChange = 'auto';
267+ node.style.backfaceVisibility = 'visible';
268+ node.style.webkitBackfaceVisibility = 'visible';
269+ }
270+ }
271+ });
272+ });
273+ });
274+
204275 function onYouTubeIframeAPIReady() {
205276 \( htmlBuilder. youTubePlayerJavaScriptVariableName) = new YT.Player(
206277 ' \( htmlBuilder. youTubePlayerJavaScriptVariableName) ',
@@ -210,9 +281,20 @@ public extension YouTubePlayer.HTMLBuilder {
210281 window.innerWidth,
211282 window.innerHeight
212283 );
284+
285+ // Optimiser pour la capture après la création du player
286+ setTimeout(() => {
287+ optimizeVideoForCapture();
288+ // Démarrer l'observation des mutations
289+ observer.observe(document.body, {
290+ childList: true,
291+ subtree: true
292+ });
293+ }, 1000);
294+
213295 sendYouTubePlayerEvent(' \( YouTubePlayer . Event. Name. iFrameApiReady. rawValue) ');
214296 }
215-
297+
216298 function sendYouTubePlayerEvent(eventName, event) {
217299 const url = new URL(` \( htmlBuilder. youTubePlayerEventCallbackURLScheme) ://${eventName}`);
218300 if (event && event.data !== null) {
@@ -224,6 +306,35 @@ public extension YouTubePlayer.HTMLBuilder {
224306 window.location.href = url.toString();
225307 }
226308
309+ // Fonction globale pour préparer la capture (appelée depuis Swift)
310+ window.prepareForCapture = function() {
311+ return new Promise(resolve => {
312+ // Forcer le rendu des vidéos
313+ const videos = document.querySelectorAll('video');
314+ videos.forEach(video => {
315+ const display = video.style.display;
316+ video.style.display = 'none';
317+ video.offsetHeight; // Force reflow
318+ video.style.display = display || '';
319+
320+ // S'assurer que la vidéo est visible
321+ video.style.opacity = '1';
322+ video.style.visibility = 'visible';
323+ });
324+
325+ // Attendre que le rendu soit stabilisé
326+ setTimeout(() => {
327+ resolve(videos.length);
328+ }, 200);
329+ });
330+ };
331+
332+ // Appliquer les optimisations dès que possible
333+ document.addEventListener('DOMContentLoaded', optimizeVideoForCapture);
334+
335+ // Optimiser périodiquement (au cas où de nouveaux éléments seraient ajoutés)
336+ setInterval(optimizeVideoForCapture, 2000);
337+
227338 \(
228339 YouTubePlayer
229340 . Event
0 commit comments