├── .gitattributes
├── README.md
├── img
└── WhisperFlow_img.png
└── src
├── WhisperFlow.py
└── requirements.txt
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
WhisperFlow: Files to YouTube, Infinite Storage Made Witty
2 |
3 |
4 | A Python program that hilariously bends the rules of space, time, and YouTube. Turn your files into magical videos, effortlessly bypassing storage limitations!
5 |
6 |
7 |
8 | Features •
9 | Usage •
10 | Examples •
11 | Contributing •
12 | License
13 |
14 |
15 | ---
16 |
17 | Are you tired of mundane storage options for your files? Seeking a solution that merges files and videos into a dazzling spectacle? Look no further, for WhisperFlow is here to delightfully defy the laws of digital storage!
18 |
19 | ### Features
20 |
21 | - **YouTube Integration**: Transform your files into captivating videos ready for YouTube upload, seamlessly merging the virtual realms of data and visual content.
22 | - **Infinite Storage Magic**: Harness the power of illusion as your files find a new home within the vast expanse of YouTube's storage capacity.
23 |
24 | ### Usage
25 |
26 | 1. **Installation**: Clone the WhisperFlow repository and install the required dependencies:
27 | - ```git clone https://github.com/yourusername/whisperflow.git```
28 | - ```cd whisperflow```
29 | - ```pip install -r requirements.txt```
30 |
31 | 2. **File Transformation**: Run the `whisperflow.py` script to convert your files into enchanting videos:
32 | - ```python whisperflow.py --file ```
33 |
34 | 3. **YouTube Upload**: Follow the on-screen prompts to upload your magically transformed video to YouTube, tapping into unlimited storage possibilities.
35 |
36 | ### Examples
37 |
38 | These are some examples showcasing the infinite storage prowess of WhisperFlow:
39 |
40 | - Hiding an entire collection of memes inside a 1 second long video.
41 | - Sharing .exe files through Gmail under video format.
42 | - Storing tons of data inside a YouTube video.
43 |
44 | ### Contributing
45 |
46 | Contributions to WhisperFlow are more than welcome! If you have any ideas for improvements, sarcastic comments to add, or magical features to implement, feel free to open an issue or submit a pull request.
47 |
48 | ### License
49 |
50 | WhisperFlow is released under the "You can do" license. You are granted the power to use, modify, and distribute this program while keeping a mischievous grin on your face.
51 |
52 | ---
53 |
54 | So why settle for conventional storage methods when you can embrace the enchanting realm of WhisperFlow? Witness the fusion of files and videos, and embark on an extraordinary journey beyond the boundaries of ordinary data storage. Let the whispers of your files flow seamlessly into the infinite expanse of YouTube, where storage limitations vanish like a puff of smoke. Happy WhisperFlowing!
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/img/WhisperFlow_img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JoshuaKasa/WhisperFlow/9bc58ef228f845c9d9b1430c9e268c5d6794de94/img/WhisperFlow_img.png
--------------------------------------------------------------------------------
/src/WhisperFlow.py:
--------------------------------------------------------------------------------
1 | import tkinter
2 | import imageio
3 | import time
4 | import math
5 | import os
6 |
7 | import numpy as np
8 |
9 | from tqdm import tqdm
10 | from tkinter import filedialog
11 | from PIL import Image
12 |
13 | # Getting the binary data of a file and calculating the progression using tqdm
14 | def get_binary_data(file_path: str) -> bytes:
15 | file_size = os.path.getsize(file_path)
16 | chunk_size = 1024 # Adjust the chunk size as per your preference
17 |
18 | with open(file_path, "rb") as file, tqdm(total=file_size, desc="Reading file", unit="B", unit_scale=True,
19 | bar_format="{desc}: {percentage:3.0f}%|{bar}| {n_fmt}/{total_fmt}") as pbar:
20 | binary_data = b""
21 | while True:
22 | chunk = file.read(chunk_size)
23 | if not chunk:
24 | break
25 | binary_data += chunk
26 | pbar.update(len(chunk))
27 |
28 | return binary_data
29 |
30 | # Getting the binary data from the video and calculating the progression using tqdm
31 | def extract_binary_data_from_video(video_path: str, width: int, height: int) -> str:
32 | binary_data = ""
33 | with imageio.get_reader(video_path, mode='I') as reader, tqdm(total=reader.count_frames(),
34 | desc='Extracting frames',
35 | bar_format="{desc}: {percentage:3.0f}%|{bar}| {n_fmt}/{total_fmt}") as pbar:
36 | for frame in reader:
37 | image = Image.fromarray(frame)
38 | red_channel = image.split()[0] # Get the red channel directly
39 |
40 | binary_data += "".join("1" if pixel & 0x80 else "0" for pixel in red_channel.getdata())
41 | pbar.update(1)
42 |
43 | return binary_data
44 |
45 | def create_images_from_binary(binary_data: bytes, width: int, height: int) -> list:
46 | binary_string = "".join(format(c, "08b") for c in binary_data)
47 | num_images = math.ceil(len(binary_string) / (width * height))
48 |
49 | images = []
50 |
51 | # Use tqdm to track the progress of the loop
52 | with tqdm(total=num_images, desc="Creating images",
53 | bar_format="{desc}: {percentage:3.0f}%|{bar}| {n_fmt}/{total_fmt}") as pbar:
54 | for i in range(num_images):
55 | start_idx = i * (width * height)
56 | end_idx = start_idx + (width * height)
57 | image_data = binary_string[start_idx:end_idx]
58 |
59 | pixels = [255 if bit == "1" else 0 for bit in image_data] # Use list comprehension for efficient pixel creation
60 |
61 | image = Image.new("L", (width, height))
62 | image.putdata(pixels)
63 | images.append(image)
64 |
65 | pbar.update(1) # Update progress bar
66 |
67 | return images
68 |
69 | def create_video(images: list, output_path: str) -> None:
70 | with imageio.get_writer(output_path, mode='I') as writer:
71 | for image in tqdm(images, desc="Creating video", bar_format="{desc}: {percentage:3.0f}%|{bar}| {n_fmt}/{total_fmt}"):
72 | frame = np.array(image)
73 | writer.append_data(frame)
74 |
75 | print("Video created successfully!")
76 |
77 | # Convert a string of bits to bytes
78 | def bits_to_file(binary_data: str) -> bytes:
79 | bytes_ = [int(binary_data[i:i+8], 2) for i in range(0, len(binary_data), 8)]
80 | return bytes(bytes_) # Convert the list of integers to bytes
81 |
82 | def select_files() -> list:
83 | tkinter.Tk().withdraw()
84 | files = filedialog.askopenfilenames()
85 | return list(files)
86 |
87 | def main() -> None:
88 | # Get the file path
89 | tkinter.Tk().withdraw()
90 | file_path = filedialog.askopenfilename()
91 | file_extension = file_path.split(".")[-1] # Get the file extension
92 |
93 | # Getting the binary data of the file
94 | initial_binary_data = get_binary_data(file_path)
95 | initial_binary_data_bits = "".join(format(c, "08b") for c in initial_binary_data) # Convert the binary data to a string of bits
96 | initial_binary_data_length = len(initial_binary_data_bits)
97 |
98 | # Specify the width and height of your images
99 | width = 1024
100 | height = 576
101 | images = create_images_from_binary(initial_binary_data, width, height)
102 | output_path = "output.mp4"
103 |
104 | # Creating the video
105 | start_time = time.time() # Start the timer
106 | create_video(images, output_path)
107 | end_time = time.time() # End the timer
108 | print("Video created successfully!")
109 | print("Time taken: {} seconds".format(end_time - start_time), "\nFor a file of size: {} bytes".format(len(initial_binary_data)))
110 |
111 | # Getting the binary data from the video and truncating it to the length of the initial binary data
112 | binary_data = extract_binary_data_from_video(output_path, width, height)
113 | binary_data = binary_data[:initial_binary_data_length]
114 |
115 | # Turning the binary data back into a file
116 | bytes_ = bits_to_file(binary_data) # Convert the binary data to bytes
117 | with open("output.{}".format(file_extension), "wb") as file:
118 | file.write(bytes_) # Write the bytes to the file
119 | print("File created successfully!")
120 |
121 | if __name__ == "__main__":
122 | main()
--------------------------------------------------------------------------------
/src/requirements.txt:
--------------------------------------------------------------------------------
1 | imageio==2.9.0
2 | numpy==1.22.0
3 | Pillow==9.3.0
4 | tqdm==4.61.2
5 | PyNaCl==1.4.0
--------------------------------------------------------------------------------