Skip to content

Commit 8748273

Browse files
[mirotalk] - fix: resolve Safari autoplay, duplicate tile, and audio re-attach issues on mobile
1 parent 345ecef commit 8748273

7 files changed

Lines changed: 27 additions & 17 deletions

File tree

.env.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# ====================================================
2-
# MiroTalk P2P v.1.8.33 - Environment Configuration
2+
# MiroTalk P2P v.1.8.34 - Environment Configuration
33
# ====================================================
44

55
# App environment

app/src/config.template.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
/**
44
* ==============================================
5-
* MiroTalk P2P v.1.8.33 - Configuration File
5+
* MiroTalk P2P v.1.8.34 - Configuration File
66
* ==============================================
77
*
88
* This file is the central configuration source.

app/src/server.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ dependencies: {
4545
* @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon
4646
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661
4747
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
48-
* @version 1.8.33
48+
* @version 1.8.34
4949
*
5050
*/
5151

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mirotalk",
3-
"version": "1.8.33",
3+
"version": "1.8.34",
44
"description": "A free WebRTC browser-based video call",
55
"main": "server.js",
66
"scripts": {

public/js/brand.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ let brand = {
109109
},
110110
about: {
111111
imageUrl: '../images/mirotalk-logo.gif',
112-
title: 'WebRTC P2P v1.8.33',
112+
title: 'WebRTC P2P v1.8.34',
113113
html: `
114114
<button
115115
id="support-button"

public/js/client.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon
1616
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661
1717
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
18-
* @version 1.8.33
18+
* @version 1.8.34
1919
*
2020
*/
2121

@@ -2893,13 +2893,16 @@ async function handleOnTrack(peer_id, peers) {
28932893
// Helper to load or attach stream
28942894
const handleStream = (elementId, streamType) => {
28952895
const element = getId(`${peer_id}___${elementId}`);
2896-
const hasStream = element?.srcObject && (elementId === 'audio' || hasVideoTrack(element.srcObject));
28972896

2898-
if (!hasStream) {
2897+
if (!element) {
2898+
// Tile doesn't exist yet — create everything
28992899
loadRemoteMediaStream(inbound, allPeers || peers, peer_id, streamType);
29002900
} else {
2901+
// Tile already exists (e.g. peer joined with camera off) — just attach the new stream
29012902
attachMediaStream(element, inbound);
29022903
elemDisplay(element, true, 'block');
2904+
// Safari requires an explicit play() after srcObject is reassigned
2905+
element.play().catch(() => {});
29032906
}
29042907
};
29052908

@@ -2908,12 +2911,11 @@ async function handleOnTrack(peer_id, peers) {
29082911

29092912
if (audioElement) {
29102913
attachMediaStream(audioElement, inbound);
2911-
if (!audioElement.srcObject) {
2912-
audioElement.play().catch((err) => {
2913-
console.warn('[AUDIO] Autoplay not allowed by device, setting up fallback:', err);
2914-
handleAudioFallback(audioElement, peer_name);
2915-
});
2916-
}
2914+
// Always call play() — srcObject was just assigned so the old check (!srcObject) was always false
2915+
audioElement.play().catch((err) => {
2916+
console.warn('[AUDIO] Autoplay not allowed by device, setting up fallback:', err);
2917+
handleAudioFallback(audioElement, peer_name);
2918+
});
29172919
} else {
29182920
loadRemoteMediaStream(inbound, allPeers || peers, peer_id, 'audio');
29192921
}
@@ -4779,6 +4781,7 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
47794781
remoteMedia.setAttribute('id', peer_id + '___video');
47804782
remoteMedia.setAttribute('playsinline', true);
47814783
remoteMedia.autoplay = true;
4784+
remoteMedia.muted = true; // audio is handled by a separate <audio> element; muting allows autoplay on Safari
47824785
remoteMediaControls = isMobileDevice ? false : remoteMediaControls;
47834786
remoteMedia.style.objectFit = 'var(--video-object-fit)';
47844787
remoteMedia.style.name = peer_id + '_typeCam';
@@ -4804,6 +4807,8 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
48044807
videoMediaContainer.appendChild(remoteVideoWrap);
48054808
// attachMediaStream is a part of the adapter.js library
48064809
attachMediaStream(remoteMedia, stream);
4810+
// Explicitly play – required on mobile Safari where autoplay alone is not enough
4811+
remoteMedia.play().catch(() => {});
48074812

48084813
// resize video elements
48094814
adaptAspectRatio();
@@ -4997,6 +5002,7 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
49975002
remoteScreenMedia.setAttribute('id', peer_id + '___screen');
49985003
remoteScreenMedia.setAttribute('playsinline', true);
49995004
remoteScreenMedia.autoplay = true;
5005+
remoteScreenMedia.muted = true; // audio is handled by a separate <audio> element; muting allows autoplay on Safari
50005006
remoteScreenMedia.controls = remoteMediaControls;
50015007
remoteScreenMedia.style.objectFit = 'contain';
50025008
remoteScreenMedia.style.name = peer_id + '_typeScreen';
@@ -5017,6 +5023,8 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
50175023

50185024
videoMediaContainer.appendChild(remoteScreenWrap);
50195025
attachMediaStream(remoteScreenMedia, stream);
5026+
// Explicitly play – required on mobile Safari where autoplay alone is not enough
5027+
remoteScreenMedia.play().catch(() => {});
50205028
adaptAspectRatio();
50215029

50225030
// handle remote private messages
@@ -12852,6 +12860,8 @@ function setPeerVideoStatus(peer_id, status) {
1285212860
{ element: peerVideoPlayer, display: true, mode: 'block' },
1285312861
{ element: peerVideoAvatarImage, display: false },
1285412862
]);
12863+
// Safari requires explicit play() when a video element becomes visible again
12864+
if (peerVideoPlayer) peerVideoPlayer.play().catch(() => {});
1285512865
if (peerVideoStatus) {
1285612866
setMediaButtonsClass([{ element: peerVideoStatus, status: true, mediaType: 'video' }]);
1285712867
setTippy(peerVideoStatus, 'Participant video is on', 'bottom');
@@ -15813,7 +15823,7 @@ function showAbout() {
1581315823
Swal.fire({
1581415824
background: swBg,
1581515825
position: 'center',
15816-
title: brand.about?.title && brand.about.title.trim() !== '' ? brand.about.title : 'WebRTC P2P v1.8.33',
15826+
title: brand.about?.title && brand.about.title.trim() !== '' ? brand.about.title : 'WebRTC P2P v1.8.34',
1581715827
imageUrl: brand.about?.imageUrl && brand.about.imageUrl.trim() !== '' ? brand.about.imageUrl : images.about,
1581815828
customClass: { image: 'img-about' },
1581915829
html: renderRoomTemplate('tpl-about-modal', {

0 commit comments

Comments
 (0)