How to output long (30min-2h) videos?

When using the Video component to output a video that are around 40 mins long, I encounter timeouts. Could someone please suggest a workaround for outputing long videos?

Replicating the issue

If you donโ€™t have a >40 min mp4 h264 encoded video available locally, download the Blender Bunny video (https://ia803407.us.archive.org/0/items/big-bunny-sample-video/SampleVideo.mp4) and run the following command, it takes seconds and the output is 416MBs:

ffmpeg -stream_loop 40 -i SampleVideo.mp4 -c copy LongSampleVideo.mp4

import gradio as gr

def greet(name):
    return "Hello " + name + "!"

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    output = gr.Textbox(label="Output Box")
    greet_btn = gr.Button("Greet")
    greet_btn.click(fn=greet, inputs=name, outputs=output)
    # input components above are just dummies to ensure that output loads
    gr.Video("LongSampleVideo.mp4")
demo.queue() # a futile attempt to avoid timeouts
demo.launch()

Error

TimeoutError                              Traceback (most recent call last)
File ~/Coding/clipit/.env/lib/python3.10/site-packages/urllib3/connectionpool.py:449, in HTTPConnectionPool._make_request(self, conn, method, url, timeout, chunked, **httplib_request_kw)
    445         except BaseException as e:
    446             # Remove the TypeError from the exception chain in
    447             # Python 3 (including for exceptions like SystemExit).
    448             # Otherwise it looks like a bug in the code.
--> 449             six.raise_from(e, None)
    450 except (SocketTimeout, BaseSSLError, SocketError) as e:

File <string>:3, in raise_from(value, from_value)

File ~/Coding/clipit/.env/lib/python3.10/site-packages/urllib3/connectionpool.py:444, in HTTPConnectionPool._make_request(self, conn, method, url, timeout, chunked, **httplib_request_kw)
    443 try:
--> 444     httplib_response = conn.getresponse()
    445 except BaseException as e:
    446     # Remove the TypeError from the exception chain in
    447     # Python 3 (including for exceptions like SystemExit).
    448     # Otherwise it looks like a bug in the code.

File /usr/local/Cellar/python@3.10/3.10.5/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py:1374, in HTTPConnection.getresponse(self)
   1373 try:
-> 1374     response.begin()
   1375 except ConnectionError:

File /usr/local/Cellar/python@3.10/3.10.5/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py:318, in HTTPResponse.begin(self)
    317 while True:
--> 318     version, status, reason = self._read_status()
    319     if status != CONTINUE:

File /usr/local/Cellar/python@3.10/3.10.5/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py:279, in HTTPResponse._read_status(self)
    278 def _read_status(self):
--> 279     line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
    280     if len(line) > _MAXLINE:

File /usr/local/Cellar/python@3.10/3.10.5/Frameworks/Python.framework/Versions/3.10/lib/python3.10/socket.py:705, in SocketIO.readinto(self, b)
    704 try:
--> 705     return self._sock.recv_into(b)
    706 except timeout:

TimeoutError: timed out

During handling of the above exception, another exception occurred:

ReadTimeoutError                          Traceback (most recent call last)
File ~/Coding/clipit/.env/lib/python3.10/site-packages/requests/adapters.py:440, in HTTPAdapter.send(self, request, stream, timeout, verify, cert, proxies)
    439 if not chunked:
--> 440     resp = conn.urlopen(
    441         method=request.method,
    442         url=url,
    443         body=request.body,
    444         headers=request.headers,
    445         redirect=False,
    446         assert_same_host=False,
    447         preload_content=False,
    448         decode_content=False,
    449         retries=self.max_retries,
    450         timeout=timeout
    451     )
    453 # Send the request.
    454 else:

File ~/Coding/clipit/.env/lib/python3.10/site-packages/urllib3/connectionpool.py:785, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
    783     e = ProtocolError("Connection aborted.", e)
--> 785 retries = retries.increment(
    786     method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2]
    787 )
    788 retries.sleep()

File ~/Coding/clipit/.env/lib/python3.10/site-packages/urllib3/util/retry.py:550, in Retry.increment(self, method, url, response, error, _pool, _stacktrace)
    549 if read is False or not self._is_method_retryable(method):
--> 550     raise six.reraise(type(error), error, _stacktrace)
    551 elif read is not None:

File ~/Coding/clipit/.env/lib/python3.10/site-packages/urllib3/packages/six.py:770, in reraise(tp, value, tb)
    769         raise value.with_traceback(tb)
--> 770     raise value
    771 finally:

File ~/Coding/clipit/.env/lib/python3.10/site-packages/urllib3/connectionpool.py:703, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
    702 # Make the request on the httplib connection object.
--> 703 httplib_response = self._make_request(
    704     conn,
    705     method,
    706     url,
    707     timeout=timeout_obj,
    708     body=body,
    709     headers=headers,
    710     chunked=chunked,
    711 )
    713 # If we're going to release the connection in ``finally:``, then
    714 # the response doesn't need to know about the connection. Otherwise
    715 # it will also try to release it and we'll have a double-release
    716 # mess.

File ~/Coding/clipit/.env/lib/python3.10/site-packages/urllib3/connectionpool.py:451, in HTTPConnectionPool._make_request(self, conn, method, url, timeout, chunked, **httplib_request_kw)
    450 except (SocketTimeout, BaseSSLError, SocketError) as e:
--> 451     self._raise_timeout(err=e, url=url, timeout_value=read_timeout)
    452     raise

File ~/Coding/clipit/.env/lib/python3.10/site-packages/urllib3/connectionpool.py:340, in HTTPConnectionPool._raise_timeout(self, err, url, timeout_value)
    339 if isinstance(err, SocketTimeout):
--> 340     raise ReadTimeoutError(
    341         self, url, "Read timed out. (read timeout=%s)" % timeout_value
    342     )
    344 # See the above comment about EAGAIN in Python 3. In Python 2 we have
    345 # to specifically catch it and throw the timeout error

ReadTimeoutError: HTTPConnectionPool(host='127.0.0.1', port=7884): Read timed out. (read timeout=3)

During handling of the above exception, another exception occurred:

ReadTimeout                               Traceback (most recent call last)
Input In [55], in <cell line: 11>()
      9     gr.Video("LongSampleVideo.mp4")
     10 demo.queue()
---> 11 demo.launch()

File ~/Coding/clipit/.env/lib/python3.10/site-packages/gradio/blocks.py:933, in Blocks.launch(self, inline, inbrowser, share, debug, enable_queue, max_threads, auth, auth_message, prevent_thread_lock, show_error, server_name, server_port, show_tips, height, width, encrypt, favicon_path, ssl_keyfile, ssl_certfile, ssl_keyfile_password, quiet, _frontend)
    930 # If running in a colab or not able to access localhost,
    931 # a shareable link must be created.
    932 is_colab = utils.colab_check()
--> 933 if is_colab or (_frontend and not networking.url_ok(self.local_url)):
    934     if not self.share:
    935         raise ValueError(
    936             "When running in Google Colab or when localhost is not accessible, a shareable link must be created. Please set share=True."
    937         )

File ~/Coding/clipit/.env/lib/python3.10/site-packages/gradio/networking.py:180, in url_ok(url)
    178 with warnings.catch_warnings():
    179     warnings.filterwarnings("ignore")
--> 180     r = requests.head(url, timeout=3, verify=False)
    181 if r.status_code in (200, 401, 302):  # 401 or 302 if auth is set
    182     return True

File ~/Coding/clipit/.env/lib/python3.10/site-packages/requests/api.py:102, in head(url, **kwargs)
     91 r"""Sends a HEAD request.
     92 
     93 :param url: URL for the new :class:`Request` object.
   (...)
     98 :rtype: requests.Response
     99 """
    101 kwargs.setdefault('allow_redirects', False)
--> 102 return request('head', url, **kwargs)

File ~/Coding/clipit/.env/lib/python3.10/site-packages/requests/api.py:61, in request(method, url, **kwargs)
     57 # By using the 'with' statement we are sure the session is closed, thus we
     58 # avoid leaving sockets open which can trigger a ResourceWarning in some
     59 # cases, and look like a memory leak in others.
     60 with sessions.Session() as session:
---> 61     return session.request(method=method, url=url, **kwargs)

File ~/Coding/clipit/.env/lib/python3.10/site-packages/requests/sessions.py:529, in Session.request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    524 send_kwargs = {
    525     'timeout': timeout,
    526     'allow_redirects': allow_redirects,
    527 }
    528 send_kwargs.update(settings)
--> 529 resp = self.send(prep, **send_kwargs)
    531 return resp

File ~/Coding/clipit/.env/lib/python3.10/site-packages/requests/sessions.py:645, in Session.send(self, request, **kwargs)
    642 start = preferred_clock()
    644 # Send the request
--> 645 r = adapter.send(request, **kwargs)
    647 # Total elapsed time of the request (approximately)
    648 elapsed = preferred_clock() - start

File ~/Coding/clipit/.env/lib/python3.10/site-packages/requests/adapters.py:532, in HTTPAdapter.send(self, request, stream, timeout, verify, cert, proxies)
    530     raise SSLError(e, request=request)
    531 elif isinstance(e, ReadTimeoutError):
--> 532     raise ReadTimeout(e, request=request)
    533 elif isinstance(e, _InvalidHeader):
    534     raise InvalidHeader(e, request=request)

ReadTimeout: HTTPConnectionPool(host='127.0.0.1', port=7884): Read timed out. (read timeout=3)