├── .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 | WhisperFlow 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 --------------------------------------------------------------------------------