[Python] Issues with Decrypting Video and Audio Reordering Using Random State in Python

Discussão em 'Python' iniciado por Stack, Janeiro 12, 2025.

  1. Stack

    Stack Membro Participativo

    I am working on a project where I reorder the seconds of audio and frames of video using a random state in Python, with the goal of "encrypting" the order. After reordering, I save the random state in order to later "decrypt" the video and audio by restoring the original order. However, when attempting to decrypt the reordered video and audio using the saved random state, the final video does not show the original order of frames and audio chunks as expected.

    Despite properly saving the random state and attempting to restore it during decryption, the decryption process is not reversing the shuffling correctly, resulting in incorrect video and audio sequences in the final output. The issue might stem from incorrect handling of the random state or the sequence of frames and audio chunks, which affects the restoration process.

    What I tried:

    I attempted to reorder the frames of a video and the chunks of an audio track using a random state in Python. The goal was to "encrypt" the order of the video frames and audio by shuffling them randomly. To enable later decryption and restore the original order, I saved the random state used for shuffling.

    For the decryption process, I tried restoring the random state to reverse the shuffling, expecting that the video frames and audio chunks would return to their original order based on the random state I saved earlier.

    What I expected:

    I expected that when I restored the saved random state during the decryption process, the original order of the video frames and audio chunks would be correctly restored. Specifically, the decrypted video should display the frames and audio in their original order as they were before the shuffling occurred.

    This would effectively "undo" the reordering and yield the original video and audio files.

    Here is my encryption code:

    import os
    import random
    import pickle
    from moviepy import VideoFileClip, AudioFileClip, ImageSequenceClip
    import librosa
    import soundfile as sf
    from pydub import AudioSegment
    import shutil

    # Save the random state using pickle
    def save_random_state_pickle(secret_word, filename='random_state.pkl'):
    random_state = random.getstate()
    with open(filename, 'wb') as f:
    pickle.dump(random_state, f)


    # Load the random state using pickle
    def load_random_state_pickle(filename='random_state.pkl'):
    try:
    with open(filename, 'rb') as f:
    state = pickle.load(f)
    random.setstate(state)
    except FileNotFoundError:
    print(f"Warning: {filename} not found. Starting with a new random state.")

    def extract_and_reorder_audio_video(video_file, secret_word, chunk_duration=1, output_folder='output_videos'):
    try:
    # Ensure the output folder exists
    os.makedirs(output_folder, exist_ok=True)

    # Define output file names
    base_name = os.path.splitext(os.path.basename(video_file))[0]
    output_video = os.path.join(output_folder, f"{base_name}_reordered.mp4")
    output_audio = os.path.join(output_folder, f"{base_name}_reordered.wav")

    # Load video clip and extract audio
    video_clip = VideoFileClip(video_file)
    audio_clip = video_clip.audio
    audio_file = f"{base_name}.wav"
    audio_clip.write_audiofile(audio_file)

    # Process audio: split into chunks and reorder
    y, sr = librosa.load(audio_file, sr=None)
    chunk_samples = int(chunk_duration * sr)
    chunks = [y[i:i + chunk_samples] for i in range(0, len(y), chunk_samples)]

    os.makedirs('audioChunks', exist_ok=True)
    for i, chunk in enumerate(chunks):
    sf.write(f'audioChunks/chunk_{i}.wav', chunk, sr)

    # List audio files in 'audioChunks' folder and sort by their chunk number
    audio_files = [f for f in os.listdir('audioChunks') if f.endswith(('.wav', '.mp3', '.flac'))]
    audio_files.sort(key=lambda f: int(f.split('_')[1].split('.')[0])) # Sort by chunk number

    # Shuffle the audio files deterministically using the secret word
    random.seed(secret_word)
    random.shuffle(audio_files)
    print("Shuffled audio files:", audio_files)

    # Combine shuffled audio chunks
    combined_audio = AudioSegment.empty()
    for idx, file in enumerate(audio_files):
    new_name = f"{secret_word}_{idx}{os.path.splitext(file)[1]}"
    os.rename(os.path.join('audioChunks', file), os.path.join('audioChunks', new_name))
    audio = AudioSegment.from_file(os.path.join('audioChunks', new_name))
    combined_audio += audio

    # Export the combined audio after shuffling
    combined_audio.export(output_audio, format="wav")
    print(f"Reordered audio saved as {output_audio}.")

    # Reorder video frames
    frames = [frame for frame in video_clip.iter_frames(fps=video_clip.fps, dtype='uint8')]
    random.shuffle(frames)

    # Create the reordered video
    reordered_video = ImageSequenceClip(frames, fps=video_clip.fps)

    # Load the reordered audio and set it to the video
    reordered_audio = AudioFileClip(output_audio)
    reordered_video.audio = reordered_audio

    # Save the final video with reordered audio
    reordered_video.write_videofile(output_video, codec='libx264')
    print(f"Reordered video saved as {output_video}.")

    except Exception as e:
    print(f"Error processing {video_file}: {e}")

    finally:
    # Cleanup temporary files and folders
    try:
    if os.path.exists(audio_file):
    os.remove(audio_file)
    if os.path.exists(output_audio):
    os.remove(output_audio)
    if os.path.exists('audioChunks'):
    shutil.rmtree('audioChunks')
    print("Temporary files and folders cleaned up.")
    except Exception as cleanup_error:
    print(f"Cleanup error: {cleanup_error}")

    def process_folder(folder_path, secret_word, chunk_duration=1):
    video_files = [f for f in os.listdir(folder_path) if f.endswith(('.mp4', '.mov', '.avi', '.mkv'))]
    for video_file in video_files:
    full_path = os.path.join(folder_path, video_file)
    print(f"Processing {full_path}...")
    extract_and_reorder_audio_video(full_path, secret_word, chunk_duration)

    # Usage
    folder = 'videos' # Folder containing video files
    process_folder(folder, 'password') # Replace 'password' with your secret word

    # Save random state after processing
    save_random_state_pickle('password')


    and here the decryption one:

    import os
    import random
    import shutil
    import pickle
    import librosa
    import soundfile as sf
    from moviepy import VideoFileClip, ImageSequenceClip, AudioFileClip
    from tkinter import filedialog, simpledialog, messagebox
    import numpy as np

    # Load the random state from the pickle file
    def load_random_state_pickle(filename='random_state.pkl'):
    try:
    with open(filename, 'rb') as f:
    state = pickle.load(f)
    random.setstate(state)
    except FileNotFoundError:
    print(f"Warning: {filename} not found. Starting with a new random state.")

    def decrypt_audio_video(file_path, secret_word, chunk_duration=1, output_folder='output_decrypted'):
    try:
    # Ensure the output folder exists
    os.makedirs(output_folder, exist_ok=True)

    # Define output file names
    base_name = os.path.splitext(os.path.basename(file_path))[0].replace("_reordered", "")
    output_video = os.path.join(output_folder, f"{base_name}_original.mp4")
    output_audio = os.path.join(output_folder, f"{base_name}_original.wav")

    # Load video clip
    video_clip = VideoFileClip(file_path)
    if not video_clip:
    raise ValueError("Invalid video file. Please check the file format.")

    # Check if video clip has audio
    if video_clip.audio is None:
    raise ValueError("The video file does not contain audio.")

    # Extract audio from the video file
    reordered_audio_file = f"{base_name}_reordered.wav"
    video_clip.audio.write_audiofile(reordered_audio_file)

    # Process audio: split into chunks and reorder
    y, sr = librosa.load(reordered_audio_file, sr=None)
    chunk_samples = int(chunk_duration * sr)
    chunks = [y[i:i + chunk_samples] for i in range(0, len(y), chunk_samples)]

    # Load random state from pickle before shuffling
    load_random_state_pickle()

    # Generate the same shuffled order using the secret_word
    random.seed(secret_word)
    chunk_order = list(range(len(chunks)))
    random.shuffle(chunk_order)
    print("Chunk order (encryption):", chunk_order)

    # Reverse the shuffle to restore original order
    original_order = [None] * len(chunk_order)
    for idx, shuffled_idx in enumerate(chunk_order):
    original_order[shuffled_idx] = idx
    print("Original order (decryption):", original_order)

    # Reconstruct audio
    reconstructed_audio = [chunks for i in original_order]
    final_audio = np.concatenate(reconstructed_audio)
    sf.write(output_audio, final_audio, sr)
    print(f"Decrypted audio saved as {output_audio}.")

    # Decrypt video frames
    frames = list(video_clip.iter_frames(fps=video_clip.fps, dtype='uint8'))
    shuffled_indices = list(range(len(frames)))

    # Restore the same random state and shuffle
    random.seed(secret_word)
    random.shuffle(shuffled_indices)
    print("Frame order (encryption):", shuffled_indices)

    # Reverse the shuffle for frames
    original_frame_order = [None] * len(shuffled_indices)
    for idx, shuffled_idx in enumerate(shuffled_indices):
    original_frame_order[shuffled_idx] = idx
    print("Original frame order (decryption):", original_frame_order)

    original_frames = [frames for i in original_frame_order]

    # Create the restored video
    restored_video = ImageSequenceClip(original_frames, fps=video_clip.fps)

    restored_audio = AudioFileClip(output_audio)
    restored_video.audio = restored_audio

    # Save the restored video
    restored_video.write_videofile(output_video, codec='libx264')
    print(f"Decrypted video saved as {output_video}.")

    except Exception as e:
    print(f"Error processing {file_path}: {e}")

    finally:
    # Cleanup temporary files
    try:
    if os.path.exists(reordered_audio_file):
    os.remove(reordered_audio_file)
    print("Temporary files cleaned up.")
    except Exception as cleanup_error:
    print(f"Cleanup error: {cleanup_error}")

    def get_file_path():
    # Open a file dialog to choose the file
    file_path = filedialog.askopenfilename(title="Select a video file", filetypes=[("Video Files", "*.mp4;*.mov;*.avi;*.mkv")])
    if not file_path:
    messagebox.showerror("Error", "No file selected. Please select a video file.")
    return file_path

    def get_secret_word():
    # Ask the user for a secret word
    secret_word = simpledialog.askstring("Input", "Enter the secret word to decrypt the video:")
    print(secret_word)
    if not secret_word:
    messagebox.showerror("Error", "No secret word provided. Please enter a valid secret word.")
    return secret_word

    def main():
    # Set up Tkinter root window (hidden)
    import tkinter as tk
    root = tk.Tk()
    root.withdraw() # Hide the root window

    file_path = get_file_path()
    if not file_path:
    return # Exit if no file is selected

    secret_word = get_secret_word()
    if not secret_word:
    return # Exit if no secret word is entered

    # Decrypt the selected video file
    decrypt_audio_video(file_path, secret_word)

    if __name__ == "__main__":
    main()

    Continue reading...

Compartilhe esta Página