Is there any way to save a dirty canvas?

后端 未结 3 980
夕颜
夕颜 2021-01-21 06:57

I am making screenshots of videos with HTML5 canvas, the video is hosted elsewhere, everything works except toDataURL() because the canvas is dirty. So, I am wondering, is ther

3条回答
  •  隐瞒了意图╮
    2021-01-21 07:20

    I tried the copying of the canvas but this just returned the same dirty canvas error.

    In the end to get this work I implemented a small service that would extract remote sources (videos) and make them look as though they were local i.e. by reading the source server side and writing out to my HTML/JS page. Once this was done it all worked fine.

    I used Python / Flask to do this, here is the snippet. Not perfect in regards to handle partial content requests but should get someone going.

    To use it I access my videos using: /remote?url=

    from datetime import timedelta
    from flask import make_response, request, current_app, Flask, url_for, render_template, Response
    from functools import update_wrapper
    import requests
    import logging
    import json
    from werkzeug.datastructures import Headers
    import httplib
    import os
    import subprocess
    import base64
    httplib.HTTPConnection.debuglevel = 1
    
    app = Flask(__name__)
    
    
    logging.basicConfig() 
    logging.getLogger().setLevel(logging.DEBUG)
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.DEBUG)
    requests_log.propagate = True
    
    def crossdomain(origin=None, methods=None, headers=None,
                    max_age=21600, attach_to_all=True,
                    automatic_options=True):
        if methods is not None:
            methods = ', '.join(sorted(x.upper() for x in methods))
        if headers is not None and not isinstance(headers, basestring):
            headers = ', '.join(x.upper() for x in headers)
        if not isinstance(origin, basestring):
            origin = ', '.join(origin)
        if isinstance(max_age, timedelta):
            max_age = max_age.total_seconds()
    
        def get_methods():
            if methods is not None:
                return methods
    
            options_resp = current_app.make_default_options_response()
            return options_resp.headers['allow']
    
        def decorator(f):
            def wrapped_function(*args, **kwargs):
                if automatic_options and request.method == 'OPTIONS':
                    resp = current_app.make_default_options_response()
                else:
                    resp = make_response(f(*args, **kwargs))
                if not attach_to_all and request.method != 'OPTIONS':
                    return resp
    
                h = resp.headers
    
                h['Access-Control-Allow-Origin'] = origin
                h['Access-Control-Allow-Methods'] = get_methods()
                h['Access-Control-Max-Age'] = str(max_age)
                if headers is not None:
                    h['Access-Control-Allow-Headers'] = headers
                return resp
    
            f.provide_automatic_options = False
            return update_wrapper(wrapped_function, f)
        return decorator
    
    def stream_remote(url, headers=None):
        logging.debug(headers) 
        range = headers["Range"]
        logging.debug(range)
        r = requests.get(url, stream=True, headers={"range":range})
        logging.debug(r.headers)
        for block in r.iter_content(1024):
            if not block:
                break
            yield block
    
    
    @app.route('/remote/')
    def get_remote():
        # Gets a remote file to make it look like it is local for CORS purposes
        url = request.args.get("url", None)
        resp_headers = Headers()
        resp_headers.add('Accept-Ranges','bytes')
    
        if url is None:
            return "Error. No URL provided"
        else:
            headers = request.headers
            logging.debug(headers)
            return Response(stream_remote(url, headers),mimetype='video/mp4',headers=resp_headers)
    
    if __name__ == '__main__':
        app.debug = True
        app.run(host="127.0.0.1", port=9001)
    

提交回复
热议问题