amazon-chime-sdk-component-library-react icon indicating copy to clipboard operation
amazon-chime-sdk-component-library-react copied to clipboard

Sharing a pdf

Open henlamk opened this issue 4 years ago • 2 comments

Describe the bug We are sharing a .pdf file via await meetingManager.audioVideo?.startContentShare(mediaStream) and it is immediately shown in the video grid of the user (User A) sharing the file. However, the other user (User B) is first shown a gray/black video tile, indicating that User A is sharing content. Only after User A continues to the next page of the pdf, the content share tile of User B contains correct content.

To Reproduce Steps to reproduce the behavior:

  1. Join a meeting with two users
  2. One starts sharing a pdf
  3. See error as the other user does not get correct content

Expected behavior User B getting the pdf displayed immediately.

Desktop (please complete the following information):

  • OS: macOS 11.2.3
  • Browser: Chrome 89.0.4389.82, Firefox 86.0.1
  • Version react lib: 2.1.0
  • Version Amazon Chime JS Sdk: 2.5.0

Additional context We are using this package for handling PDFs: https://www.npmjs.com/package/react-pdf

henlamk avatar Mar 15 '21 19:03 henlamk

@henlamk Can you give us a snippet of the code you used react-pdf to generate the media stream? Also is there any error/warning in console?

ltrung avatar Mar 15 '21 19:03 ltrung

No, there is no error/warning ocuring in the console.

Below you can see the stripped down component, that we use to control the content play.

pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`

export const RemotePdfPlay: React.FC<any> = (props) => {
  const dispatch = useDispatch()
  const meetingManager = useMeetingManager()
  const pdfContent = useSelector((state) => state.video.pdfContent) // This is just a fileblob, set in another component

  const canvasRef = React.useRef()
  const canvasContextRef = React.useRef()

  const [numPages, setNumPages] = useState<any>(null)
  const [pageNumber, setPageNumber] = useState<any>(1)
  const [isStreaming, setIsStreaming] = useState(false)
  const [documentLoaded, setDocumentLoaded] = useState(false)
  const [currentCanvas, setCurrentCanvas] = useState<any>()

  async function renderCanvas() {
    if (canvasRef.current && canvasContextRef.current && currentCanvas) {
      const pdf: any = currentCanvas
      const canvas: any = canvasRef.current
      const ctx: any = canvasContextRef.current

      ctx!.fillStyle = "white"
      ctx!.fillRect(0, 0, canvas.width, canvas.height)

      const hRatio = canvas.width / pdf.width
      const vRatio = canvas.height / pdf.height
      const ratio = Math.min(hRatio, vRatio)
      const centerShift_x = (canvas.width - pdf.width * ratio) / 2
      const centerShift_y = (canvas.height - pdf.height * ratio) / 2

      ctx!.drawImage(pdf, 0, 0, pdf.width, pdf.height, centerShift_x, centerShift_y, pdf.width * ratio, pdf.height * ratio)
    }
  }

  async function streamCanvas() {
    let mediaStream: any
    const canvas: any = document.createElement("canvas")
    canvasRef.current = canvas
    canvas.width = 1280
    canvas.height = 720
    const ctx = canvas.getContext("2d")
    canvasContextRef.current = ctx

    mediaStream = canvas!.captureStream()
    await meetingManager.audioVideo?.startContentShare(mediaStream)
    setIsStreaming(true)
  }

  async function canvasCallback() {
    if (!isStreaming) {
      await streamCanvas()
      return
    }
    if (isStreaming) await renderCanvas()
  }

  useEffect(() => {
    if (currentCanvas) canvasCallback()
  }, [currentCanvas])

  return (
    <div className="mt-5 p-5 bg-white rounded" style={{ boxShadow: "4px 4px 10px -1px rgba(0,0,0,0.75)" }}>
      {pdfContent && (
        <>
          <div style={{ display: "none" }}>
            <Document
              file={pdfContent}
              onLoadSuccess={({ numPages }) => {
                setNumPages(numPages)
                setDocumentLoaded(true)
              }}
            >
              {documentLoaded && (
                // @ts-ignore
                <Page pageNumber={pageNumber} canvasRef={(data) => setCurrentCanvas(data)} onRenderSuccess={renderCanvas} />
              )}
            </Document>
          </div>
        </>
      )}
      <div>
        {pdfContent && (
          <div className="flex space-x-4">
            {numPages > 1 && (
              <>
                <button
                  disabled={pageNumber == 1}
                  onClick={() => {
                    setPageNumber(pageNumber - 1)
                  }}
                >
                  Zurück
                </button>
                <button
                  disabled={pageNumber == numPages}
                  onClick={() => {
                    setPageNumber(pageNumber + 1)
                  }}
                >
                  Weiter
                </button>
              </>
            )}

            <button
              onClick={() => {
                meetingManager.audioVideo?.stopContentShare()
                dispatch(setPdfContent(null))
              }}
            >
              Beenden
            </button>

            <div>
              {pageNumber} / {numPages}
            </div>
          </div>
        )}
      </div>
    </div>
  )
}

henlamk avatar Mar 22 '21 09:03 henlamk