Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exported video are different to original video dimension #18

Open
aleczratiu opened this issue Feb 19, 2020 · 2 comments
Open

Exported video are different to original video dimension #18

aleczratiu opened this issue Feb 19, 2020 · 2 comments

Comments

@aleczratiu
Copy link

aleczratiu commented Feb 19, 2020

I try to record a video with custom dimension 720x1280 or 1280x720.
I expected the output to have the same dimension with the original video but the recorded video add some black space on top and bottom and (width, height) are different then original dimension.

Tell us about your environment:
Puppeteer version: 2.1.1
Platform: docker ubuntu

Landscape example:
Dimension used in export.js and background.js (width: 1280, height: 720)
Original video:

Exported record video:

If you see the last frame from exported video are the real size from original video size.

Portrait example
Dimension used in export.js and background.js (width: 720, height: 1280)
Original video:

Exported record video:

Used code for bunny example, in second example just dimension are different.
export.js

const express = require ('express');
const puppeteer = require('puppeteer');
const Xvfb      = require('xvfb');
var xvfb        = new Xvfb({silent: false});

const chromeExtensionPath = `${__dirname}/chrome-extension`;

// export DISPLAY=:99 && /etc/init.d/xvfb start

async function main() {
    const PARTIAL_CONTENT_STATUS = 206;

    return new Promise(async (resolve, reject) => {
        try {
            let browser = await puppeteer.launch({
                headless: false,
                devtools: false,
                executablePath: '/usr/bin/google-chrome',
                ignoreDefaultArgs: ['--mute-audio'],
                defaultViewport: {
                    width: 1280,
                    height: 720,
                },
                args: [
                    '--enable-usermedia-screen-capturing',
                    '--allow-http-screen-capture',
                    '--auto-select-desktop-capture-source=puppetcam',
                    '--load-extension=' + chromeExtensionPath,
                    '--disable-extensions-except=' + chromeExtensionPath,
                    '--disable-infobars',
                    '--no-sandbox',
                    '--hide-scrollbars',
                    '--window-size=1280,720',
                ],
            });

            const page = await browser.newPage();

            page.setViewport({
                width: 1280,
                height: 720,
            })

            page.on('console', msg => console.log('PAGE LOG:', msg.text()));
            page.on('error', (e) => {
                reject(e);
                browser.close().catch(console.error);
            });
            page.on('requestfailed', (req) => {
                const response = req.response();
                if (response && response.status() === PARTIAL_CONTENT_STATUS) {
                    console.log([
                        'Ignoring failed request for ',
                        req.url(),
                        ' with status 206 Partial Content. Range: ',
                        response && response.headers()['content-range'],
                    ].join(''));
                } else {
                    console.error('requestfailed', req.url(), req.failure().errorText);
                }
            });

            const response = await page.goto('http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', {waitUntil: 'networkidle2'})

            await page.waitFor(17000)
            xvfb.startSync()
            await page.evaluate(filename=>{
                window.postMessage({type: 'SET_EXPORT_PATH', filename: filename}, '*')
                window.postMessage({type: 'REC_STOP'}, '*')
            }, 'bunny.webm')

            // Wait for download of webm to complete
            await page.waitForSelector('html.downloadComplete', {timeout: 0})
            xvfb.stopSync()
            if (response.status() < 200 || response.status() >= 400) {
                throw new Error(`Preview server response error: ${await response.text()}`);
            }

            browser.close().catch(console.error);
        } catch (e) {
            console.error(e);

            throw e;
        }
    });
}

    const app = express();

    // cors
    app.use((req, res, next) => {
        res.header('Access-Control-Allow-Origin', '*');
        res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
        next();
    });

    // healthCheck @TODO: make it better
    app.get('/health', (req, res) => {
        res.status(200).send({ code: 200, body: 'OK' });
    });

    app.listen(4000, () => {
        console.log(`Started to listen on port 4000`);
    });


    app.get('/export', () => {
        console.log('here');
        main()
    });

background.js:

/* global chrome, MediaRecorder, FileReader */

console.log(`Background script loading`);
let recorder = null;
let filename = null;
chrome.runtime.onConnect.addListener(port => {
  port.onMessage.addListener(msg => {
    console.log(msg);
    switch (msg.type) {
      case 'SET_EXPORT_PATH':
        console.log(`set export path`);
        filename = msg.filename;
        break;
      case 'REC_STOP':
        console.log(`REC STOP`);
        recorder.stop();
        break;
      case 'REC_CLIENT_PLAY':
        if (recorder) {
          return;
        }
        const tab = port.sender.tab;
        tab.url = msg.data.url;
        const size = {width: 1280, height: 720};
        chrome.desktopCapture.chooseDesktopMedia(['tab', 'audio'], streamId => {
          // Get the stream
          navigator.webkitGetUserMedia(
            {
            audio: {
                mandatory: {
                    chromeMediaSource: 'system'
                }
            },
              video: {
                mandatory: {
                  chromeMediaSource: 'desktop',
                  chromeMediaSourceId: streamId,
                  minWidth: size.width,
                  maxWidth: size.width,
                  minHeight: size.height,
                  maxHeight: size.height,
                  minFrameRate: 60,
                },
              },
            },
            stream => {
              var chunks = [];
              recorder = new MediaRecorder(stream, {
                videoBitsPerSecond: 2500000,
                ignoreMutedMedia: true,
                mimeType: 'video/webm',
              });
              recorder.ondataavailable = function(event) {
                if (event.data.size > 0) {
                  chunks.push(event.data);
                }
              };

              recorder.onstop = function() {
                var superBuffer = new Blob(chunks, {
                  type: 'video/webm',
                });

                var url = URL.createObjectURL(superBuffer);
                // var a = document.createElement('a');
                // document.body.appendChild(a);
                // a.style = 'display: none';
                // a.href = url;
                // a.download = 'test.webm';
                // a.click();

                chrome.downloads.download(
                  {
                    url: url,
                    filename: filename,
                  },
                  () => {
                    console.log(arguments);
                  },
                );
              };

              recorder.start();
            },
            error => console.log('Unable to get user media', error),
          );
        });
        break;
      default:
        console.log('Unrecognized message', msg);
    }
  });

  chrome.downloads.onChanged.addListener(function(delta) {
    if (!delta.state || delta.state.current != 'complete') {
      return;
    }
    try {
      port.postMessage({downloadComplete: true});
    } catch (e) {}
  });
});

Dockerfile:

FROM ubuntu

ARG DEBIAN_FRONTEND=noninteractive

ENV TZ=Europe/Bucharest
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN apt-get update
RUN apt-get  install -y curl xvfb x11vnc x11-xkb-utils xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic x11-apps nodejs npm tightvncserver xfce4 xfce4-goodies apt-utils gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget x11vnc x11-xkb-utils xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic x11-apps xvfb apt-utils openvpn fping nano libgtk-3.0 libatk-bridge2.0-0


RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
    && apt-get update \
    && apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf \
      --no-install-recommends \
    && rm -rf /var/lib/apt/lists/* \
    && apt-get purge --auto-remove -y curl \
    && rm -rf /src/*.deb

## Sound options for RHEL7 OpenClient
RUN snd_opts="--device /dev/snd \
	-e PULSE_SERVER=unix:${XDG_RUNTIME_DIR}/pulse/native \
	-v ${XDG_RUNTIME_DIR}/pulse/native:${XDG_RUNTIME_DIR}/pulse/native \
	--group-add $(getent group audio | cut -d: -f3)"

RUN groupmod -g 92 audio

ADD xvfb_init /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb
ADD xvfb_daemon_run /usr/bin/xvfb-daemon-run
RUN chmod a+x /usr/bin/xvfb-daemon-run

WORKDIR /cac
ADD package.json .
RUN npm install

COPY ./app ./app

ENV DISPLAY :99
@aleczratiu aleczratiu changed the title Export video are different by original like dimension Export video are different to original dimension Feb 19, 2020
@aleczratiu aleczratiu changed the title Export video are different to original dimension Exported video are different to original dimension Feb 19, 2020
@aleczratiu aleczratiu changed the title Exported video are different to original dimension Exported video are different to original video dimension Feb 19, 2020
@zakcali
Copy link

zakcali commented May 26, 2020

try to use page.setViewport after const response = await page.goto

@muralikg
Copy link
Owner

You could try setting the screen size during initialization of xvfb and play the video in full screen mode to make sure that entire viewport is recorded.

new Xvfb({silent: true, xvfb_args: ["-screen", "0", `${width}x${height}x24`, "-ac"],});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants