admin管理员组

文章数量:1310290

I'm encountering a pending_url issue when using the D-ID API. I'm making a POST request to create a talk, which returns a 201 status code and a talk ID.
Immediately after, I'm making a GET request to retrieve the talk details using this ID. However, the GET request response includes a pending_url instead of the expected video URL.

Here's the relevant code snippet (Flask):

@app.route('/video')
def video():


    # retrieve the value of the environment variable named DID_API_KEY from .env
    did_api_key = os.getenv('DID_API_KEY')
    if len(did_api_key) != None:
        print("The function load_dotenv() has loaded the DID_API_KEY correctly.")
        print("The value of the did_api_key is: ", did_api_key)
    else:
        print("Problem loading the DID_API_KEY. Please review .env file.")
        return "Problem loading the DID_API_KEY. Please review .env file."

    # retrieve the value of the environment variable named BEARER_TOKEN from .env
    bearer_token = os.getenv('BEARER_TOKEN')
    if len(bearer_token) != None:
        print("The function load_dotenv() has loaded the BEARER_TOKEN correctly.")
        print("The value of the bearer_key  is: ", bearer_token)
    else:
        print("Problem loading the BEARER_TOKEN. Please review .env file.")
        return "Problem loading the BEARER_TOKEN. Please review .env file."



    # Create a talk POST
    # DID_API_KEY obtained. Use it to generate the AI Talking Avatar.
    import requests

    url = ";
    source_url = ".jpg"
    input_text = "Making videos is easy with D-ID"

    payload = {
        "source_url": source_url,
        "script": {
            "type": "text",
            "subtitles": "false",
            "provider": {
                "type": "microsoft",
                "voice_id": "Sara"
            },
            "input": input_text
        },
        "config": {
            "fluent": "false",
            "pad_audio": "0.0"
        }
    }

    headers = {
        "accept": "application/json",
        "content-type": "application/json",
        "authorization": "Bearer {0}".format(bearer_token)
    }


    response = requests.post(url, json=payload, headers=headers)

    if response.status_code == 402:
        # not enough d-id api credits 
        # response.text = {"kind":"InsufficientCreditsError","description":"not enough credits"} 402
        return '>>> ' + response.text + ' ' + str(response.status_code)

    if response.status_code == 201:
        # got a 201 after a POST request, it's a positive sign.
        # It confirms that the server has successfully created the resource.  

        print(response.text)
        print(response.status_code)    
        """
            {
                "id":"tlk_pCB0A1dMhZi0JfA0S8NE5",
                "created_at":"2025-02-03T20:02:39.302Z",
                "created_by":"google-oauth2|103344389677485792824",
                "status":"created",
                "object":"talk"
            }
            response.status_code equals 201    
        """



    # get a specific talk GET
    print("get a specific talk GET")

    # get the id of the video
    id_video = response.json()["id"]

    headers = {
        "accept": "application/json",
        "authorization": "Bearer {0}".format(bearer_token)
    }

    # set url
    url = "/{0}".format(id_video)

    response = requests.get(url, headers=headers)

    print(response.text)
    print(response.status_code)    
    return response.text

The POST request is successful (201), and the response contains the talk ID. However, the subsequent GET request returns a response with a pending_url and the status is started, indicating that the video processing is not yet complete. The expected behavior is for the GET request to eventually return a proper video URL when the processing is finished.

Here's an example of the GET response I'm receiving:

{
  "user": {
    "features": ["stitch", "clips:write", "scene", "premium-plus:skip-speaker-validation", null],
    "stripe_plan_group": "deid-trial",
    "authorizer": "bearer",
    "_id": null,
    "owner_id": "auth0|67a12d64c60b14766a228fda",
    "domain": ";,
    "id": "auth0|67a12d64c60b14766a228fda",
    "plan": "deid-trial",
    "email": "[email protected]"
  },
  "script": {
    "length": 31,
    "subtitles": false,
    "type": "text",
    "provider": {
      "type": "microsoft",
      "voice_id": "Sara"
    }
  },
  "audio_url": "/tlk_dhNTB5cDt-aBHUGoqN0jf/microsoft.wav?AWSAccessKeyId=AKIA5CUMPJBIK65W6FGA&Expires=1738704589&Signature=%2F3lSL1GS%2FkgK%2FH1nlLAkVYSG3rw%3D",
  "created_at": "2025-02-03T21:29:49.187Z",
  "config": {
    "stitch": false,
    "pad_audio": 0,
    "align_driver": true,
    "sharpen": true,
    "reduce_noise": false,
    "auto_match": true,
    "normalization_factor": 1,
    "show_watermark": true,
    "motion_factor": 1,
    "result_format": ".mp4",
    "fluent": false,
    "align_expand_factor": 0.3
  },
  "source_url": "/tlk_dhNTB5cDt-aBHUGoqN0jf/source/wHD7943BS.jpg?AWSAccessKeyId=AKIA5CUMPJBIK65W6FGA&Expires=1738704589&Signature=xY6c9d57Xy1gOnUhAJWK7zUtWXY%3D",
  "created_by": "auth0|67a12d64c60b14766a228fda",
  "status": "started",
  "driver_url": "bank://natural/",
  "modified_at": "2025-02-03T21:29:49.476Z",
  "user_id": "auth0|67a12d64c60b14766a228fda",
  "subtitles": false,
  "id": "tlk_dhNTB5cDt-aBHUGoqN0jf",
  "duration": 2.4625,
  "started_at": "2025-02-03T21:29:49.239",
  "pending_url": "s3://d-id-talks-prod/auth0|67a12d64c60b14766a228fda/tlk_dhNTB5cDt-aBHUGoqN0jf/1738618189187.mp4"
}

I've checked my BEARER_TOKEN and DID_API_KEY, and they are correct. How can I correctly retrieve the final video URL after the processing is complete? Is there a polling mechanism or a webhook I should be using? What is the recommended way to handle asynchronous video processing with the D-ID API?

I'm encountering a pending_url issue when using the D-ID API. I'm making a POST request to create a talk, which returns a 201 status code and a talk ID.
Immediately after, I'm making a GET request to retrieve the talk details using this ID. However, the GET request response includes a pending_url instead of the expected video URL.

Here's the relevant code snippet (Flask):

@app.route('/video')
def video():


    # retrieve the value of the environment variable named DID_API_KEY from .env
    did_api_key = os.getenv('DID_API_KEY')
    if len(did_api_key) != None:
        print("The function load_dotenv() has loaded the DID_API_KEY correctly.")
        print("The value of the did_api_key is: ", did_api_key)
    else:
        print("Problem loading the DID_API_KEY. Please review .env file.")
        return "Problem loading the DID_API_KEY. Please review .env file."

    # retrieve the value of the environment variable named BEARER_TOKEN from .env
    bearer_token = os.getenv('BEARER_TOKEN')
    if len(bearer_token) != None:
        print("The function load_dotenv() has loaded the BEARER_TOKEN correctly.")
        print("The value of the bearer_key  is: ", bearer_token)
    else:
        print("Problem loading the BEARER_TOKEN. Please review .env file.")
        return "Problem loading the BEARER_TOKEN. Please review .env file."



    # Create a talk POST
    # DID_API_KEY obtained. Use it to generate the AI Talking Avatar.
    import requests

    url = "https://api.d-id/talks"
    source_url = "https://i.imghippo/files/wHD7943BS.jpg"
    input_text = "Making videos is easy with D-ID"

    payload = {
        "source_url": source_url,
        "script": {
            "type": "text",
            "subtitles": "false",
            "provider": {
                "type": "microsoft",
                "voice_id": "Sara"
            },
            "input": input_text
        },
        "config": {
            "fluent": "false",
            "pad_audio": "0.0"
        }
    }

    headers = {
        "accept": "application/json",
        "content-type": "application/json",
        "authorization": "Bearer {0}".format(bearer_token)
    }


    response = requests.post(url, json=payload, headers=headers)

    if response.status_code == 402:
        # not enough d-id api credits 
        # response.text = {"kind":"InsufficientCreditsError","description":"not enough credits"} 402
        return '>>> ' + response.text + ' ' + str(response.status_code)

    if response.status_code == 201:
        # got a 201 after a POST request, it's a positive sign.
        # It confirms that the server has successfully created the resource.  

        print(response.text)
        print(response.status_code)    
        """
            {
                "id":"tlk_pCB0A1dMhZi0JfA0S8NE5",
                "created_at":"2025-02-03T20:02:39.302Z",
                "created_by":"google-oauth2|103344389677485792824",
                "status":"created",
                "object":"talk"
            }
            response.status_code equals 201    
        """



    # get a specific talk GET
    print("get a specific talk GET")

    # get the id of the video
    id_video = response.json()["id"]

    headers = {
        "accept": "application/json",
        "authorization": "Bearer {0}".format(bearer_token)
    }

    # set url
    url = "https://api.d-id/talks/{0}".format(id_video)

    response = requests.get(url, headers=headers)

    print(response.text)
    print(response.status_code)    
    return response.text

The POST request is successful (201), and the response contains the talk ID. However, the subsequent GET request returns a response with a pending_url and the status is started, indicating that the video processing is not yet complete. The expected behavior is for the GET request to eventually return a proper video URL when the processing is finished.

Here's an example of the GET response I'm receiving:

{
  "user": {
    "features": ["stitch", "clips:write", "scene", "premium-plus:skip-speaker-validation", null],
    "stripe_plan_group": "deid-trial",
    "authorizer": "bearer",
    "_id": null,
    "owner_id": "auth0|67a12d64c60b14766a228fda",
    "domain": "https://studio.d-id",
    "id": "auth0|67a12d64c60b14766a228fda",
    "plan": "deid-trial",
    "email": "[email protected]"
  },
  "script": {
    "length": 31,
    "subtitles": false,
    "type": "text",
    "provider": {
      "type": "microsoft",
      "voice_id": "Sara"
    }
  },
  "audio_url": "https://d-id-talks-prod.s3.us-west-2.amazonaws/auth0%7C67a12d64c60b14766a228fda/tlk_dhNTB5cDt-aBHUGoqN0jf/microsoft.wav?AWSAccessKeyId=AKIA5CUMPJBIK65W6FGA&Expires=1738704589&Signature=%2F3lSL1GS%2FkgK%2FH1nlLAkVYSG3rw%3D",
  "created_at": "2025-02-03T21:29:49.187Z",
  "config": {
    "stitch": false,
    "pad_audio": 0,
    "align_driver": true,
    "sharpen": true,
    "reduce_noise": false,
    "auto_match": true,
    "normalization_factor": 1,
    "show_watermark": true,
    "motion_factor": 1,
    "result_format": ".mp4",
    "fluent": false,
    "align_expand_factor": 0.3
  },
  "source_url": "https://d-id-talks-prod.s3.us-west-2.amazonaws/auth0%7C67a12d64c60b14766a228fda/tlk_dhNTB5cDt-aBHUGoqN0jf/source/wHD7943BS.jpg?AWSAccessKeyId=AKIA5CUMPJBIK65W6FGA&Expires=1738704589&Signature=xY6c9d57Xy1gOnUhAJWK7zUtWXY%3D",
  "created_by": "auth0|67a12d64c60b14766a228fda",
  "status": "started",
  "driver_url": "bank://natural/",
  "modified_at": "2025-02-03T21:29:49.476Z",
  "user_id": "auth0|67a12d64c60b14766a228fda",
  "subtitles": false,
  "id": "tlk_dhNTB5cDt-aBHUGoqN0jf",
  "duration": 2.4625,
  "started_at": "2025-02-03T21:29:49.239",
  "pending_url": "s3://d-id-talks-prod/auth0|67a12d64c60b14766a228fda/tlk_dhNTB5cDt-aBHUGoqN0jf/1738618189187.mp4"
}

I've checked my BEARER_TOKEN and DID_API_KEY, and they are correct. How can I correctly retrieve the final video URL after the processing is complete? Is there a polling mechanism or a webhook I should be using? What is the recommended way to handle asynchronous video processing with the D-ID API?

Share Improve this question edited Feb 4 at 6:51 VLAZ 29.1k9 gold badges63 silver badges84 bronze badges asked Feb 3 at 21:48 RamiroRamiro 4434 silver badges18 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Found the solution, here are the technical details:

API Polling: The code uses a while loop to repeatedly send GET requests to the API until the video response status is 'done'. This is an example of API polling, which can be used to wait for a long-running process to complete. The loop is crucial in this code snippet because it implements a technique called polling or busy waiting. This technique is used to wait for a specific condition to be met, in this case, the server responding with a 'done' status.

Here is the complete code:

@app.route('/video')
def video():

    import json

    # retrieve the value of the environment variable named DID_API_KEY from .env
    did_api_key = os.getenv('DID_API_KEY')

    # retrieve the value of the environment variable named BEARER_TOKEN from .env
    bearer_token = os.getenv('BEARER_TOKEN')



    # Create a talk POST
    # DID_API_KEY obtained. Use it to generate the AI Talking Avatar.
    import requests

    url = "https://api.d-id/talks"
    source_url = "https://i.imghippo/files/wHD7943BS.jpg"
    input_text = "Making videos is easy with D-ID"

    payload = {
        "source_url": source_url,
        "script": {
            "type": "text",
            "subtitles": "false",
            "provider": {
                "type": "microsoft",
                "voice_id": "Sara"
            },
            "input": input_text
        },
        "config": {
            "fluent": "false",
            "pad_audio": "0.0"
        }
    }

    headers = {
        "accept": "application/json",
        "content-type": "application/json",
        "authorization": f"Bearer {bearer_token}"
    }


    response = requests.post(url, json=payload, headers=headers)

    if response.status_code == 402:
        # not enough d-id api credits 
        # response.text = {"kind":"InsufficientCreditsError","description":"not enough credits"} 402
        return '>>> ' + response.text + ' ' + str(response.status_code)

    if response.status_code == 201:
        # got a 201 after a POST request, it's a positive sign.
        # It confirms that the server has successfully created the resource.  

        print(response.text)
        print(response.status_code)    
        """
            {
                "id":"tlk_pCB0A1dMhZi0JfA0S8NE5",
                "created_at":"2025-02-03T20:02:39.302Z",
                "created_by":"google-oauth2|103344389677485792824",
                "status":"created",
                "object":"talk"
            }
            response.status_code equals 201    
        """



    # get a specific talk GET
    print("get a specific talk GET")

    # get the id of the video
    id_video = response.json()["id"]

    headers = {
        "accept": "application/json",
        "authorization": f"Bearer {bearer_token}"
    }

    # set url
    url = "https://api.d-id/talks/{0}".format(id_video)
    talk_url = url 

    response = requests.get(talk_url, headers=headers)
    video_response = json.loads(response.text)

    while video_response["status"] != "done":
        # Video response status still doesn't have the value 'done'... will continue sending request.get to d-id server...
        response = requests.get(talk_url, headers=headers)
        video_response = json.loads(response.text)

    video_url = video_response["result_url"]
    # The talking avatar has been generated...
    # It will now be displayed on screen...
    return video_url

本文标签: pythonDID API pendingurl returned instead of video URL after successful POST and GETStack Overflow