zebra-spaces: request landscape camera + letterbox portrait frames
Android Chrome / Firefox getUserMedia honour aspectRatio:{ideal:16/9}
on the camera constraints to lock the sensor read-out to landscape
regardless of the device's current screen orientation. Adding it stops
the back camera from sending a portrait frame the receivers can't
rotate.
Belt-and-suspenders on the render side: camera tile video switches from
object-fit:cover to object-fit:contain so any portrait stream that
slips through (older browsers, manual override) letterboxes inside the
16:9 box instead of being middle-cropped into a square. Black
background fills the bars.
Thumbnails stay cover-cropped (visual consistency in the column);
spotlight view always uses contain.
This commit is contained in:
parent
666ba8e88a
commit
6af83eb896
1 changed files with 18 additions and 5 deletions
|
|
@ -326,8 +326,12 @@
|
|||
}
|
||||
.camera-tile video {
|
||||
width: 100%; height: auto; display: block;
|
||||
background: transparent;
|
||||
aspect-ratio: 16 / 9; object-fit: cover;
|
||||
background: #000;
|
||||
/* contain (not cover) so a portrait stream from a mobile camera
|
||||
* letterboxes inside the 16:9 box instead of being middle-cropped
|
||||
* into a square. We still reserve a 16:9 slot for layout stability
|
||||
* across mixed stream orientations. */
|
||||
aspect-ratio: 16 / 9; object-fit: contain;
|
||||
}
|
||||
.camera-tile .screen-meta {
|
||||
background: #f0f0f0; color: #333; font-size: 0.7rem; padding: 0.2rem 0.4rem;
|
||||
|
|
@ -2182,7 +2186,16 @@ async function sfuUnpublishGame(){
|
|||
async function sfuPublishCamera(){
|
||||
if (sfuCameraPC || !myKeys || !roomID) return;
|
||||
let stream;
|
||||
const videoConstraints = { width:{ideal:1280}, height:{ideal:720}, frameRate:{ideal:30} };
|
||||
/* aspectRatio:{ideal: 16/9} tells Android Chrome / Firefox to capture
|
||||
* in landscape regardless of the device's current screen orientation.
|
||||
* Without it the back camera in portrait delivers a portrait stream
|
||||
* that the receivers then cover-crop into a square. With it the
|
||||
* sensor reads out landscape and rotation no longer matters. */
|
||||
const videoConstraints = {
|
||||
width: { ideal: 1280 }, height: { ideal: 720 },
|
||||
aspectRatio: { ideal: 16/9 },
|
||||
frameRate: { ideal: 30 },
|
||||
};
|
||||
if (cameraDeviceId) videoConstraints.deviceId = { exact: cameraDeviceId };
|
||||
try {
|
||||
/* camera only — mic comes through the separate sfuPublish path so a
|
||||
|
|
@ -3696,8 +3709,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');
|
|||
|
||||
<footer style="margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
|
||||
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> · built <span class="stamp-date">2026-06-02</span><br>
|
||||
md5 <span class="stamp-md5">aca11b254d306fc675e74a2b7b76c3c9</span><br>
|
||||
sha256 <span class="stamp-sha">bf43d6fa4bec117e6e77ebe4b096ab69c0df5ed5cb76f01fc515666209ad800a</span><br>
|
||||
md5 <span class="stamp-md5">ac20654825a05d94fc8840fc14a7ccec</span><br>
|
||||
sha256 <span class="stamp-sha">4d7d6235f401636cb12b323236d4a0381a0d82a1af7e3c1bb2854a8d725a4572</span><br>
|
||||
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
|
||||
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify against these hashes; point at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
|
||||
</footer>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue