#🔒 modifying simple util to work better to source

144 messages · Page 1 of 1 (latest)

blazing willow
#
import datetime
import pathlib

# Get the path to the current location of where the script is stored
current_directory = pathlib.Path(__file__).absolute().parent
files = list(current_directory.rglob("*.mp4"))
files.sort(key=lambda path: path.stat().st_mtime)

count = 0
num = int(input("enter the video number:"))
# List all files in the current directory
for file in files:
    if file.is_file():
        name = file.name

        if file.suffix == ".mp4":
            stat = file.stat()
            ok = datetime.datetime.fromtimestamp(stat.st_mtime).strftime("%c")
            # ok not used

            file.rename(f"video-{num}.mp4")
            print(f"renamed file to video-{num}.mp4")
            print(f"original name is {name}\nDate Creation:\n{ok}")
            print("-----------------------------------------------")

            count = count + 1
            num = num + 1

print(f"{count} files found")

this doesn't acount for

paper nestBOT
#

@blazing willow

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

blazing willow
#

value:

#

Util to rename files according to Media created if exists if not path.stat().st_mtime

tacit shale
#

What are you trying to do?

blazing willow
#

however the old method relied on modifited time which makes the order funky sometimes

#

Cause I accidently downloaded it from drive rather than using the copy directly from my switch

severe kettle
#

it depends on where that piece of information is stored. mtime is the modification time ...
there is also st_ctime, which is however deprecated, and since python 3.12 there is st_birthtime.

blazing willow
#

How does one get the media created value if it does exist

#

i want media created to be the value prefered if that doesn't exist, then use path.stat().st_mtime

severe kettle
#

it's also possible that metadata is stored in the mp4 files, which is not something you can easily get access to without decoding mp4 file format.

blazing willow
#

it may be stored via metadata, I may need to link you to the google drive so you can view one of the files

#

cause discord strips metadata

pearl sphinx
#

could use exif for this

blazing willow
#

exif isn't built in tho

#

I am trying to rely on builtin as much as possible

severe kettle
#

that's true. it it's stored in the content of the file, you'd need to use a 3rd party library likely

blazing willow
#

It sucks python doesn't have a way to view this

severe kettle
#

python can't really account for every possible file format out there 😉

pearl sphinx
#

that part

blazing willow
#

I am on windows tho

#

maybe that helps?

#

oh yeah only mp4 has media created it seems

severe kettle
#

seems to be in the files metadata.

blazing willow
#

it's weird that I couldn't get the file's metadata like dictionary keys

#

so I couldn't get a dictionary lookup of media created?

pearl sphinx
#
import datetime
import pathlib
import os

def get_media_creation_date(file_path):
    # Try to get the creation time first
    try:
        creation_time = os.path.getctime(file_path)
        return datetime.datetime.fromtimestamp(creation_time)
    except:
        pass
    
    # If creation time is not available, fall back to modification time
    return datetime.datetime.fromtimestamp(os.path.getmtime(file_path))

# Get the path to the current location of where the script is stored
current_directory = pathlib.Path(__file__).absolute().parent
files = list(current_directory.rglob("*.mp4"))

# Sort files by media creation date or modification time
files.sort(key=lambda path: get_media_creation_date(path))

count = 0
num = int(input("Enter the starting video number: "))

# List all files in the current directory
for file in files:
    if file.is_file() and file.suffix.lower() == ".mp4":
        original_name = file.name
        creation_date = get_media_creation_date(file)
        
        new_name = f"video-{num:03d}_{creation_date.strftime('%Y%m%d_%H%M%S')}.mp4"
        file.rename(file.with_name(new_name))
        
        print(f"Renamed file to {new_name}")
        print(f"Original name: {original_name}")
        print(f"Creation/Modification Date: {creation_date.strftime('%c')}")
        print("-----------------------------------------------")

        count += 1
        num += 1

print(f"{count} files processed")

try to get the file creation date if not fall back to mod date, get path of dir for file(s) <- includes sub dirs, sort and rename, print out info from each file, file count

blazing willow
#

media created is not the same as file creation

#

this will not work for me

severe kettle
#

the creation date is not what we're looking for

pearl sphinx
#

I misunderstood my apologies

severe kettle
#

and ctime is not "creation time" techically anyway.

blazing willow
#

The problem is that I accidently uploaded it to google drive then downloaded it rather than using the one from my sd card.

#

so the modifitcation and created at dates are wrong

#

I need the media created to be accurate

#

otherwise the video order is wrong

severe kettle
#

you need a tool/lib that can decode the files content (mtime etc. is not part of the files content).
exiftool on linux can do that, but not sure how to get the same on windows

#

<@&831776746206265384> too late

pearl sphinx
#

go ffmpeg

blazing willow
#

ffmpeg will make it cross platform?

#

I do have ffmpeg in path tho

severe kettle
#

ffmpeg might be possible, but is also a bit overkill just for metadata

#

if you already do, sure

blazing willow
#

i mean I do need to use ffmpeg anyway

severe kettle
#

do you also have ffprobe on path? it's usually in the same location

blazing willow
#

I usually do:

import datetime
import pathlib

# Get the path to the current location of where the script is stored
current_directory = pathlib.Path(__file__).absolute().parent
files = list(current_directory.rglob("*.mp4"))
files.sort(key=lambda path: path.stat().st_mtime)

count = 0
num = int(input("enter the video number:"))
# List all files in the current directory
for file in files:
    if file.is_file():
        name = file.name

        if file.suffix == ".mp4":
            stat = file.stat()
            ok = datetime.datetime.fromtimestamp(stat.st_mtime).strftime("%c")
            # ok not used

            file.rename(f"video-{num}.mp4")
            print(f"renamed file to video-{num}.mp4")
            print(f"original name is {name}\nDate Creation:\n{ok}")
            print("-----------------------------------------------")

            count = count + 1
            num = num + 1

print(f"{count} files found")

Then:

import asyncio
import datetime
import pathlib

# Get the path to the current directory
current_directory = pathlib.Path(__file__).absolute().parent
files = list(current_directory.rglob("*.mp4"))
files.sort(key=lambda path: path.stat().st_mtime)


async def ffmpeg_shengians():
    # List all files in the current directory
    for file in files:
        if file.is_file():
            name = file.name

            if file.suffix == ".mp4":
                stat = file.stat()
                ok = datetime.datetime.fromtimestamp(stat.st_mtime).strftime("%c")
                # unused ok variable may use it for prints or something else I don't know yet.

                source_file = str(file)
                base_file = file.with_stem(f"{file.stem} upgraded")
                quality_file = file.with_stem(f"{file.stem} quality")

                proc = await asyncio.create_subprocess_exec(
                    "ffmpeg",
                    "-i",
                    source_file,
                    "-c:v",
                    "hevc_nvenc",
                    "-qp",
                    "17",
                    "-vf",
                    "scale=1920x1080:flags=lanczos",
                    base_file,
                )
                await proc.wait()

                proc = await asyncio.create_subprocess_exec(
                    "ffmpeg",
                    "-i",
                    source_file,
                    "-i",
                    base_file,
                    "-c:v",
                    "hevc_nvenc",
                    "-qp",
                    "17",
                    "-filter_complex",
                    "[0]pad=iw:1080:0:(1080-ih)/2,hstack",
                    quality_file,
                )

                await proc.wait()


asyncio.run(ffmpeg_shengians())
print("done")

blazing willow
#

yep i have ffprobe

#

notice how I use rename first then ffmpeg if I want to do bulk upconvert?

#
@echo off

:loop
set "SOURCE=%1"
set "BASE=%~n1"
set "TARGET=%BASE% upgraded.mp4"
set "QUALITY=%BASE% quality.mp4"

ffmpeg -i "%SOURCE%" -c:v hevc_nvenc -qp 17 -vf scale=1920x1080:flags=lanczos "%TARGET%"
ffmpeg -i "%SOURCE%" -i "%TARGET%" -c:v hevc_nvenc -qp 17 -filter_complex "[0]pad=iw:1080:0:(1080-ih)/2,hstack" "%QUALITY%"
shift
if not "%~1"=="" goto loop

sometimes i use just this batch file tho

#

renaming the files makes them easier to run in ffmpeg

severe kettle
#

ffprobe -i video.mp4 -loglevel error -show_entries stream_tags:format_tags

blazing willow
#

I would then upload it automatically to youtube oauth and stop when it errors.
however, youtube oauth upload is a bit problematic

#
ffprobe -i test.mp4 -loglevel error -show_entries stream_tags:format_tags
[STREAM]
TAG:creation_time=2023-01-11T06:18:37.000000Z
TAG:language=eng
TAG:handler_name=VideoHandle
TAG:vendor_id=[0][0][0][0]
[/STREAM]
[STREAM]
TAG:creation_time=2023-01-11T06:18:37.000000Z
TAG:language=eng
TAG:handler_name=SoundHandle
TAG:vendor_id=[0][0][0][0]
[/STREAM]
[FORMAT]
TAG:major_brand=mp42
TAG:minor_version=0
TAG:compatible_brands=isommp42
TAG:creation_time=2023-01-11T06:18:37.000000Z
[/FORMAT]
severe kettle
#

can even add -of json for a json output

#

the "format" section is for the mp4 container file itself I believe.

blazing willow
#
ffprobe -i test.mp4 -loglevel error -show_entries stream_tags:format_tags -of json
{
    "streams": [
        {
            "tags": {
                "creation_time": "2023-01-11T06:18:37.000000Z",
                "language": "eng",
                "handler_name": "VideoHandle",
                "vendor_id": "[0][0][0][0]"
            }
        },
        {
            "tags": {
                "creation_time": "2023-01-11T06:18:37.000000Z",
                "language": "eng",
                "handler_name": "SoundHandle",
                "vendor_id": "[0][0][0][0]"
            }
        }
    ],
    "format": {
        "tags": {
            "major_brand": "mp42",
            "minor_version": "0",
            "compatible_brands": "isommp42",
            "creation_time": "2023-01-11T06:18:37.000000Z"
        }
    }
}
#

rooThink which one is it tho?

#

Janurary 11, 2023's date.

severe kettle
#

the bottom one is for the format. which is mp4. the indiviual streams may have separate times, but they all seem to be the same anyway.

#

looks right, no? just different timezone perhaps. the Z indicates UTC, which is roughly london time... so yours is ... eastern time?

blazing willow
#
import datetime
import pathlib

# Get the path to the current location of where the script is stored
current_directory = pathlib.Path(__file__).absolute().parent
files = list(current_directory.rglob("*.mp4"))
files.sort(key=lambda path: path.stat().st_mtime)

count = 0
num = int(input("enter the video number:"))
# List all files in the current directory
for file in files:
    if file.is_file():
        name = file.name

        if file.suffix == ".mp4":
            stat = file.stat()
            ok = datetime.datetime.fromtimestamp(stat.st_mtime).strftime("%c")
            # ok not used

            file.rename(f"video-{num}.mp4")
            print(f"renamed file to video-{num}.mp4")
            print(f"original name is {name}\nDate Creation:\n{ok}")
            print("-----------------------------------------------")

            count = count + 1
            num = num + 1

print(f"{count} files found")

how would you change this to use ffmpeg's one?

severe kettle
#

write a function that does it

blazing willow
#

Yeah mine's us east

#

or america/new_york

#

I need to walk my dog

#

it's later than it should be cause I had to do first classes of semester stuff

blazing willow
# severe kettle write a function that does it
import asyncio
async def get_media_created(filename:str ):
   proc = await asyncio.create_subprocess_exec(
   [
   "ffprobe",
   "-i",
   filename,
  "-loglevel",
  "error",
  "-show_entries",
  "stream_tags:format_tags",
  "-of",
  "json"
   ] 
   await proc.wait()

  # someone use the response like json
#

something like that?

severe kettle
#

it's the same time

#

do you need async for your code?

blazing willow
#

Someone yelled at me for not using it before

#

so yeah

severe kettle
#

well, kind of silly, if you only use a few functions for that... but whatever works

blazing willow
#

What I made is funky

severe kettle
#

but yea, that seems to work. just need to read the output using PIPE

blazing willow
#

Would you be okay modifying it I really need to walk my dog

severe kettle
#

ah and you don't pass in a list

#

ok, I'll do

blazing willow
#

I put all the scripts into one

severe kettle
#

I'll just make that one function

blazing willow
#

I need to followup youtube upload oauth later

#
                    "ffmpeg",
                    "-i",
                    source_file,
                    "-c:v",
                    "hevc_nvenc",
                    "-qp",
                    "17",
                    "-vf",
                    "scale=1920x1080:flags=lanczos",
                    base_file,

I may be able to split by spaces

#

and be able to make it string later

severe kettle
#
import sys
from datetime import datetime
import zoneinfo

import json
import subprocess


def get_media_created(filename: str):
    proc = subprocess.Popen([
        "ffprobe",
        "-i",
        filename,
        "-loglevel",
        "error",
        "-show_entries",
        "stream_tags:format_tags",
        "-of",
        "json"
    ], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    output, errors = proc.communicate()

    if proc.returncode != 0:  # when not successfull, print errors and exit
        print(errors.decode('utf-8', 'replace'), file=sys.stderr)
        sys.exit(1)
    return json.loads(output)


# requires you to install tzdata on Windows!!
ny_tz = zoneinfo.ZoneInfo('America/New_York')

data = get_media_created('video2.mp4')
ctime = data['format']['tags']['creation_time']

dt = datetime.fromisoformat(ctime).astimezone(ny_tz)
print(dt)
``` if it's a different file anyway, no need to stick to async. the async stuff seems to be unrelated to the current code.
#

(the above code works with the file you provided earlier)

blazing willow
#

Although I haven't had issues with zoneinfo on windows

#

Cause I don't view the time

#

I feel like it would be best if it the value doesn't exist cause what if someone downloads a clip from discord and tries to run it that's an error

#

Hence using the og value if this doesn't work for sort

#

Does this make sense?

severe kettle
#

not sure

#

if the ffprobe extracted metadata doesn't exist, then you can just fallback to any other value

blazing willow
severe kettle
#

works as well as long as you use str() in the suprocess command on the path object

blazing willow
#

I can replace filename with that

#

And pass in path

#

Which allows path.stat()

severe kettle
#

path.name might not work, if the file is in a different directory

blazing willow
#

I try to avoid os's version cause pathlib works

severe kettle
#

os.stat works fine with path objects

blazing willow
#

No, I already have a path object

#

Which I can use

severe kettle
#

yea okay, but path.name is still incorrect technically. str(path) is the way to go

blazing willow
#

Why str(path)

#

Cause full path?

severe kettle
#

because the path might be in a different folder, and path.name only gives you the filename, without any directory context. so it can fail.

#

(even if it won't in your case because they're all in the same directory, it's still technically incorrect)

blazing willow
severe kettle
#

seems fine (except of course the incorrect call at the bottom - but that comes later)

blazing willow
#

I want to try to update the other related scripts too

Possibly make the youtube upload ouath too

#

Google's docs for it are wrong

severe kettle
#

they're probably not wrong. OAuth is not straightforward.

blazing willow
#

It has code is for python 2 not 3

severe kettle
#

okay, that doesn't make them "wrong" just outdated. And it says 2.5 or higher. which might mean python 3 is supported as well.

blazing willow
#

The last time I tried it failed

#

Cause python 3 misses a library they use

severe kettle
blazing willow
#

No, their example script is wrong

#

Wish I saved the error cause i tried the script 6 months ago which they haven't changed

#

Let me give you the error and let me update rename.py

#

Uh

#

It's not working

#

alright there

blazing willow
#

how would I Make it faster when it comes to input and such?

#
"from __future__ import print_function

import os.path

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

# If modifying these scopes, delete the file token.json.
SCOPES = ["https://www.googleapis.com/auth/youtube.upload"]

# The ID of a sample document.
DOCUMENT_ID = "195j9eDD3ccgjQRttHhJPymLJUCOUjs-jmwTrekvdjFE"


def main():
    """Shows basic usage of the Docs API.
    Prints the title of a sample document.
    """
    creds = None
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists("token.json"):
        creds = Credentials.from_authorized_user_file(
            "token.json",
            SCOPES,
        )
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                "credentials.json",
                SCOPES,
            )
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open(
            "token.json",
            "w",
        ) as token:
            token.write(creds.to_json())

    try:
        service = build(
            "docs",
            "v1",
            credentials=creds,
        )

        # Retrieve the documents contents from the Docs service.
        document = service.documents().get(documentId=DOCUMENT_ID).execute()

        print("The title of the document is: {}".format(document.get("title")))
    except HttpError as err:
        print(err)


if __name__ == "__main__":
    main()

I also so happen to have this old quickstart thingy

blazing willow
#

which helps a little

blazing willow
#

It ran better before the change unsure how to change it to run better

paper nestBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.