wkaisertexas / tiktok-uploader

Automatically ⬆️ upload TikTok videos
https://pypi.org/project/tiktok-uploader/
360 stars 84 forks source link

Attempting to add the ability to overlay the soundtrack from TikTok on video #97

Closed cprite closed 6 months ago

cprite commented 8 months ago

I've modify cli.py so now it takes one more additional argument "soundtrack" as an input when run the main file.

def main():
    """
    Passes arguments into the program
    """
    args = get_uploader_args()

    args = validate_uploader_args(args=args)

    # parse args
    schedule = parse_schedule(args.schedule)
    proxy = parse_proxy(args.proxy)

    # runs the program using the arguments provided
    result = upload_video(
        filename=args.video,
        description=args.description,
        soundtrack=args.soundtrack, # NEW INPUT PARAMETER
        schedule=schedule,
        username=args.username,
        password=args.password,
        cookies=args.cookies,
        proxy=proxy,
        sessionid=args.sessionid,
        headless=not args.attach,
    )

    print('-------------------------')
    if result:
        print('Error while uploading video')
    else:
        print('Video uploaded successfully')
    print('-------------------------')
def get_uploader_args():
    """
    Generates a parser which is used to get all of the video's information
    """
    parser = ArgumentParser(
        description='TikTok uploader is a video uploader which can upload a' +
        'video from your computer to the TikTok using selenium automation'
    )

    # primary arguments
    parser.add_argument('-v', '--video', help='Video file', required=True)
    parser.add_argument('-d', '--description', help='Description', default='')

    # secondary arguments
    parser.add_argument('-sn', '--soundtrack', help='Soundrack', default='') # NEW ARGUMENT

Then I tried to modify upload.py file to add actual steps for adding soundtrack to the video using Selenium lib:

# NEW FUNCTION
def _set_soundtrack(driver, soundtrack: str) -> None:
    """
    Sets the soundtrack of the video

    Parameters
    ----------
    driver : selenium.webdriver
    soundtrack : str
        The soundtrack to set
    """
    if soundtrack is None:
        # if no soundtrack is provided
        return

    logger.debug(green('Setting soundtrack'))

    # Remove any characters outside the BMP range (emojis, etc) & Fix accents
    soundtrack = soundtrack.encode('utf-8', 'ignore').decode('utf-8')

    # Press "Edit video" to start
    edit_video_button = WebDriverWait(driver, 120).until(EC.presence_of_element_located((By.XPATH, '//*[@id="root"]/div/div/div/div[1]/div[1]/div[2]/button')))
    edit_video_button.click()

    logger.debug(green('Press "Edit video" button'))

    # Wait for the search field to appear
    search_field_xpath = "//*[@id='tux-portal-container']/div[2]/div/div/div/div/div[2]/div/div[3]/div[1]/div[2]/div/div[1]/div/div[2]/input"
    search_field = WebDriverWait(driver, config['explicit_wait']).until(EC.visibility_of_element_located((By.XPATH, search_field_xpath)))
    logger.debug(green('Find search bar'))

    # Click the search field to focus
    search_field.click()
    logger.debug(green('Press search field to focus'))

    # Enter soundtrack name
    search_field.send_keys(soundtrack)
    WebDriverWait(driver, config['explicit_wait']).until(lambda d: search_field.get_attribute('value') != '')
    logger.debug(green('Enter soundtrack name'))
    try:
        # Wait for the result of the search to appear
        choose_soundtrack_xpath = '//*[@id="tux-portal-container"]/div[2]/div/div/div/div/div[2]/div/div[3]/div[1]/div[2]/div/div[2]/div[1]/div[1]/button'
        choose_soundtrack_button = WebDriverWait(driver, config['explicit_wait']).until(EC.presence_of_element_located((By.XPATH, choose_soundtrack_xpath)))
        # Choose first soundrack category apearing in the search result
        choose_soundtrack_button.click()
        logger.debug(green('Choose soundtrack category'))

        # Wait for the music_menu_button to appear
        music_menu_xpath = '//*[@id="tux-portal-container"]/div[2]/div/div/div/div/div[2]/div/div[3]/div[1]/div[2]/div/div[2]/div/div/div[1]'
        music_menu_button = WebDriverWait(driver, config['explicit_wait']).until(EC.presence_of_element_located((By.XPATH, music_menu_xpath)))
        # Put cursor on the first soundrack to enable "Use" button
        hover = ActionChains(driver).move_to_element(music_menu_button)
        hover.perform()
        logger.debug(green('Put cursor on soundtrack'))

        # Press "Use" button to apply soundtrack on the video
        use_button_xpath = '//*[@id="tux-portal-container"]/div[2]/div/div/div/div/div[2]/div/div[3]/div[1]/div[2]/div/div[2]/div/div/div[1]/div/div[2]/button'
        use_button = WebDriverWait(driver, config['explicit_wait']).until(EC.presence_of_element_located((By.XPATH, use_button_xpath)))
        use_button.click()
        logger.debug(green('Press "Use" button'))

        # Wait for "Save edit" button to appear and click to confirm changes
        save_edit_button_xpath = '//*[@id="tux-portal-container"]/div[2]/div/div/div/div/div[2]/div/div[1]/span/div/div[2]/button[2]'
        save_edit_button = WebDriverWait(driver, config['explicit_wait']).until(EC.presence_of_element_located((By.XPATH, save_edit_button_xpath)))
        # Press "Save edit" button to confirm changes
        save_edit_button.click()
        logger.debug(green('Press "Save edit" button'))
    except Exception as exception:
        print('Failed to set soundtrack: ', exception)
        # Click the "Cancel" button
        cancel_button_xpath = '//*[@id="tux-portal-container"]/div[2]/div/div/div/div/div[2]/div/div[1]/span/div/div[2]/button[1]'
        cancel_button = WebDriverWait(driver, config['explicit_wait']).until(EC.presence_of_element_located((By.XPATH, cancel_button_xpath)))
        cancel_button.click()

        # Wait for the "Close" button to appear and click it
        close_button_xpath = '//*[@id="tux-portal-container"]/div[5]/div/div/div/div/div[2]/div/div/button[1]'
        close_button = WebDriverWait(driver, config['explicit_wait']).until(EC.presence_of_element_located((By.XPATH, close_button_xpath)))
        # Press "Close" button to confirm
        close_button.click()

but the problem is that it fails with error when tries to find the location of the search bar to send soundtrack name to it. If anyone have any ideas how to solve this problem, I would be very grateful. Thank you