13

It's been a while since I uploaded my latest screenshot to Steam, because mere 4 gigabytes of cloud space granted by Valve got exhausted really fast. In the meantime I still continued to take screenshots, with Steam and with other tools, saving them locally and patiently waiting when upload limits are increased, so I can upload all this stuff again.

And the screenshot space finally got increased to whopping 20 GB! This means we can now upload tons of screenshots we made since the last cloud space bump.

But unfortunately something has changed and now I can't upload any old screenshots. I wrote "custom" in the question's title, but in my case screenshots are custom basically because they were taken with some third party utility or even with PrtScr and Ctrl + V.

The new naming scheme is YYYMMDDHHMMSS_1.jpg, files are still saved to C:\Program Files (x86)\Steam\userdata\<user id>\<some number>\remote\<game id>\screenshots, and when you place your custom screenshots to this folder, Steam screenshot uploader sees them, creates thumbnails, but refuses to upload. Now it only uploads screenshots actually taken with Steam.

So guides like this one became obsolete. The notorious "Steam Cloud may be temporarily unavailable" error appears. I'm sure custom screenshots still can be uploaded, but the whole process apparently now is more tricky.

Anyone able to crack this for us screenshotheads?

  • Would adding them as "Artwork" suffice in this instance? – Mano Aug 19 '16 at 21:06
  • 1
    Nope. Artwork is considered a very different matter in Steam universe. No one would be pleased if I pollute game's hub artwork space with dozens of mere screenshots. – TranslucentCloud Aug 19 '16 at 21:07
  • This has always been a huge pain for me. I usually just end up running Win media center as a game, opening the images and screencapping them again through steam. They won't get uploaded as the game you want though, even if you rename the app. – GnomeSlice Aug 19 '16 at 21:10
  • 2
    By the way someone with 300 reputation or more, create a screenshot tag. I believe this tag is essential to ArQAde. – TranslucentCloud Aug 19 '16 at 21:14
  • 1
    @Sumurai8 okay I got it, nobody loves screenshot. Let's get straight to the topic. – TranslucentCloud Aug 20 '16 at 8:47
18

The process of uploading a (custom) screenshot is similar to what it used to be.

First find the relevant folder for the game you want to upload screenshots for. This is usually something like C:\Program Files (x86)\Steam\userdata\<user id>\<some number>\remote\<game id>\screenshots\. Refer to this guide (also linked in the question) if you still need help finding the game id. Put your screenshots in that folder. Open steam, right-click the game and click "Show screenshots". Let it load all the thumbnails. Exit the dialog, then exit steam completely (by right-clicking the notification icon and clicking "Exit").

Go to C:\Program Files (x86)\Steam\userdata\<user id>\<some number>\ (that is a few folders above the folder you put your screenshots in, and open screenshots.vdf in an editor that respects both windows and unix line endings, such as VIM or Notepad++. Now find the entry for each of your screenshots. In my case I was searching for the screenshot 20160809224314_2.jpg.

Editing screenshots.vdf in vim

The problem you encountered is because Steam now fills in the vrfilename entry with a non-existing file. Remove that filename so that it says "vrfilename" "". You might need to set imported to "0" depending on if you tried to upload it before.

Removed vrfilename and set imported to 0 for my screenshot

Save the file, then start steam again. Right-click the game again, then click "show screenshots". It now should allow you to upload your image.

  • Well, that's solves a problem of uploading a one or a couple of screenshots, upvoted, but not solves the problem of uploading a couple of thousands of them. Currently I'm working on a tool that automates the process and will post it as my own answer. – TranslucentCloud Aug 20 '16 at 11:41
  • 1
    If you don't use vr, you probably can just mass replace the string (e.g. something like s/^\s+"vrfilename"\s*".+"/ "vrfilename" ""/g in vim) – Sumurai8 Aug 20 '16 at 12:00
  • 1
    Screenshots should be mass-renamed too. And to something meaningful, such as creation date from EXIF. There are a lot of problems which cannot be solved by hand. – TranslucentCloud Aug 20 '16 at 12:06
12
+100

Well, I promised to come back here with my own solution to this problem, and here I am with a cross-platform open-source utility to simplify the whole process.

At first I thought I'd do it as a Windows batch file, but doesn't provide a good way to work with regular expressions. Then I thought maybe Python script will do it, but hey, nobody wants to install an interpreter and mess with command-line tools. At last I thought I should give Qt a try, and I didn't regret that choice!

Meet SteaScree, Steam Cloud screenshot uploader: https://steascree.download

Here is what it is like: enter image description here

It's a bit ugly, but Qt has messy UI builder, and this is my first software project in recent times, so please don't judge by the looks.

The sources are shared via GitHub, so if you'd like to report a bug or improve this tool, welcome. This is my first project with Qt, so there may be some issues. Please report them on the GitHub as well.

  • 2
    It always happen in these kind of sites where there's a karma system. Is great to keep the content good but it brings an unhealthy amount of elitism. Happy to hear your app is being useful to people. :) I'll open an issue later because I found that some screenshot are not being upended by steam successfully. :( – Deses Dec 11 '16 at 13:44
  • Wow, thanks for the bounty @Cristol.GdM. It was totally unexpected. – TranslucentCloud Jul 25 at 14:59
4

Steam doesn't care about filename nor creation date. After you upload screenshot there is only "upload date" displayed. Real date is only used in Screenshots window so you see them ordered properly before upload.

While Sumurai8's answer is complete, some people may have problem with locating proper directory. That's why I wrote script to automate it a bit. It requires Python (you need to install it if you have Windows, other systems should already have it) and VDF Python module.

#!/usr/bin/env python
from __future__ import print_function
from time import sleep
import vdf, platform, os, glob, codecs, subprocess, shutil, time, sys
try:
    import winreg
except ImportError:
    import _winreg as winreg
try:
    input = raw_input
except NameError:
    pass
def find_default_steam_path():
    return {
        "Windows": lambda: winreg.QueryValueEx(
            winreg.CreateKey(winreg.HKEY_CURRENT_USER,r"Software\Valve\Steam"),
            "SteamPath"
        )[0],
        "Linux": lambda: os.path.expanduser("~/.local/share/Steam"),
        "Darwin": lambda: os.path.expanduser("~/Library/Application Support/Steam")
    }[platform.system()]()
def get_libraries(path):
    libraries = [path]
    ignored = ["TimeNextStatsReport", "ContentStatsID"]
    for k, v in vdf.parse(open(os.path.join(path, "steamapps", "libraryfolders.vdf")))["LibraryFolders"].items():
        if k not in ignored:
            libraries.append(os.path.normpath(v))
    return libraries
def get_games_vdfs(libs):
    vdfs = []
    for lib in libs:
        vdfs += glob.glob(os.path.join(lib, "steamapps", "*.acf"))
    return vdfs
def get_users(path):
    users = []
    for k, v in vdf.parse(open(os.path.join(path, "config", "loginusers.vdf")))["users"].items():
        users.append([v["PersonaName"], str(int(k)-0x110000100000000)])
    return sorted(users, key=lambda x: x[0].lower())
def get_user_data(path, user_id):
    return vdf.parse(codecs.open(os.path.join(path, "userdata", user_id, "config", "localconfig.vdf"), 'r', 'utf8'))["UserLocalConfigStore"]
def get_games(vdfs):
    games = []
    for v in vdfs:
        game = vdf.parse(open(v))["AppState"]
        if all(g[1] != game["appid"] for g in games):
            games.append([game["name"], game["appid"]])
    return sorted(games, key=lambda x: x[0].lower())
def filter_user_games(games, user_data):
    user_games = list(user_data["Licenses"].keys()) + list(user_data["apptickets"].keys())
    for game in games:
        if game[1] not in user_games:
            games.remove(game)
def get_last_game_index(games, user_data):
    last_played = ["", 0]
    for game, v in user_data["Software"]["Valve"]["Steam"]["Apps"].items():
        lp = int(v["LastPlayed"])
        if lp > last_played[1]:
            last_played = [game, lp]
    for i, game in enumerate(games):
        if game[1] == last_played[0]:
            return i
steam_path = os.path.normpath(find_default_steam_path())
steam_binary = os.path.join(steam_path, "steam" + (".exe" if platform.system() == "Windows" else ""))
if not os.path.exists(steam_path):
    steam_path = input("Enter main Steam directory location: ")
users = get_users(steam_path)
libraries = get_libraries(steam_path)
if len(users) == 1:
    user = users[0]
else:
    for i, u in enumerate(users):
        print(i, u[0], sep = ". ")
    user = users[int(input("Choose user: "))]
user_data = get_user_data(steam_path, user[1])
games_vdfs = get_games_vdfs(libraries)
games = get_games(games_vdfs)
filter_user_games(games, user_data)
last_played_index = get_last_game_index(games, user_data)
print()
for i, g in enumerate(games):
    print(i, g[0], sep = ". ")
game_choice = input("Choose game or leave empty for last played game (" + games[last_played_index][0] + "): ")
if game_choice == "":
    game_choice = last_played_index
game = games[int(game_choice)]
print()
screenshot_info_path = os.path.join(steam_path, "userdata", user[1], "760")
dst_path = os.path.join(screenshot_info_path, "remote", game[1], "screenshots")
screenshot_info_path = os.path.join(screenshot_info_path, "screenshots.vdf")
try:
    os.makedirs(dst_path)
except OSError:
    pass
src_path = input("Enter source directory: ")
if len(src_path) > 1 and src_path[0] in ('"\'') and src_path[-1] == src_path[0]:
    src_path = src_path[1:-1]
files_to_move = glob.glob(os.path.join(src_path, "*.[jJ][pP][gG]"))
if len(files_to_move) == 0:
    input("No files to move. Press Enter to exit.")
    sys.exit(1)
for file in files_to_move:
    shutil.move(file, dst_path)
if os.path.exists(screenshot_info_path):
    size_old = os.stat(screenshot_info_path)[-4]
else:
    size_old = 0
mod_old = -1
subprocess.Popen([steam_binary, "steam://open/screenshots"])
while True:
    size_new, _, mod_new = os.stat(screenshot_info_path)[-4:-1]
    if size_old != size_new:
        size_old = size_new
        mod_old = mod_new
    elif mod_old > -1 and time.time() - mod_old > 3:
        break
    sleep(1)
subprocess.call([steam_binary, "-shutdown"])
screenshot_info = vdf.parse(codecs.open(screenshot_info_path, 'r', 'utf8'))
for k, v in screenshot_info["Screenshots"].items():
    for k2, v2 in v.items():
        screenshot_info["Screenshots"][k][k2]["vrfilename"] = ""
vdf.dump(screenshot_info, codecs.open(screenshot_info_path, 'w', 'utf8'))
input("All done! Wait until Steam client closes and press Enter to start it again.")
subprocess.Popen([steam_binary, "steam://open/screenshots"])

How to use?

  1. Save it for example as steam_custom_screenshots.py
  2. On Linux and Mac make it executable
  3. Close Steam
  4. Run script

    • If script can't find Steam installation dir, it will ask you for one
    • If more than one user logged in to Steam on this computer, script will ask you to choose your account
    • You will be asked to choose a game
    • You will be asked to choose a path to your screenshots
    • Script will now move all *.jpg files from path you entered in previous step to correct directory, start Steam so it imports screenshots, close Steam, edit screenshots.vdf file and wait for you to press Enter to run Steam again.

If you still have any problem uploading screenshots, delete Steam/userdata/<your ID>/760/screenshots.vdf file and try again. I just uploaded 283 files this way.

Sidenote: There are several default locations of Steam on Linux machines depending on how you install it. I don't know them, so if you want to share one or you know how to find it with Python, let me know in comment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.