Created
August 16, 2023 02:28
-
-
Save noahlias/df5de36c02e62e0a3b5aed1a58f5a80e to your computer and use it in GitHub Desktop.
video_to_ascii
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SFML/Audio.hpp> | |
#include <chrono> | |
#include <iostream> | |
#include <opencv2/opencv.hpp> | |
#include <thread> | |
using namespace std; | |
using namespace cv; | |
void playAudio(const string& audio_path) { | |
sf::Music music; | |
if (!music.openFromFile(audio_path)) { | |
cout << "Error loading audio from video." << endl; | |
return; | |
} | |
music.play(); | |
while (music.getStatus() == sf::Music::Playing) { | |
std::this_thread::sleep_for( | |
std::chrono::milliseconds(10)); // Sleep for a short duration | |
} | |
} | |
string pixelToASCII(int pixel_intensity) { | |
// const string ASCII_CHARS = "@$%#&!*+=-_. "; | |
// const string ASCII_CHARS = | |
// "@B%8WM#*oahkbdpwmZO0QCJYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. "; const | |
// string ASCII_CHARS = "@#&!*+=-_. "; | |
const string ASCII_CHARS = " ._-=+*!&#%$@"; | |
string s = | |
string(1, ASCII_CHARS[pixel_intensity * ASCII_CHARS.length() / 256]); | |
return s; | |
} | |
int main(int argc, char** argv) { | |
if (argc < 3) { | |
cout << "Usage: " << argv[0] << " <video_path> <audio_path>" << endl; | |
return -1; | |
} | |
string video_path = argv[1]; | |
string audio_path = argv[2]; | |
VideoCapture cap(video_path); | |
double fps = cap.get(CAP_PROP_FPS); | |
// cout << fps << endl; | |
int frame_duration_ms = 1000 / fps; | |
int width = 85; | |
int height = 30; | |
int frame_width = cap.get(CAP_PROP_FRAME_WIDTH); | |
int frame_height = cap.get(CAP_PROP_FRAME_HEIGHT); | |
// cout << frame_width << " " << frame_height << endl; | |
// 4096 2160 | |
// 751 × 944 | |
// height = (width * frame_height / frame_width) * 0.4194; | |
Mat frame, gray_frame, resized_frame; | |
auto video_start_time = std::chrono::high_resolution_clock::now(); | |
bool isFirstFrame = true; | |
for (int frame_number = 0;; ++frame_number) { | |
cap >> frame; | |
if (frame.empty()) break; | |
cv::cvtColor(frame, gray_frame, cv::COLOR_BGR2GRAY); | |
resize(gray_frame, resized_frame, Size(width, height), 0, 0, INTER_LINEAR); | |
string ascii_frame; | |
for (int i = 0; i < height; i++) { | |
for (int j = 0; j < width; j++) { | |
ascii_frame += pixelToASCII(resized_frame.at<uchar>(i, j)); | |
} | |
ascii_frame += "\n"; | |
} | |
system("clear"); | |
cout << ascii_frame; | |
if (isFirstFrame) { | |
std::thread audioThread(playAudio, audio_path); | |
audioThread.detach(); | |
isFirstFrame = false; | |
} | |
auto current_time = std::chrono::high_resolution_clock::now(); | |
auto since_video_start = | |
std::chrono::duration_cast<std::chrono::milliseconds>(current_time - | |
video_start_time); | |
auto next_frame_time = frame_number * frame_duration_ms; | |
if (since_video_start.count() < next_frame_time) { | |
std::this_thread::sleep_for(std::chrono::milliseconds( | |
next_frame_time - since_video_start.count())); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
build.sh
You need install
SFML
andOpenCV
first.Getting Started
Download the video and mp3. Then run the program
And you get the gif.