Код: Выделить всё
make
Код: Выделить всё
splitter видеофайл.mp4 0:0:59 0:1:37
Код: Выделить всё
make
Код: Выделить всё
splitter видеофайл.mp4 0:0:59 0:1:37
Код: Выделить всё
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdlib> // Для system()
#include <algorithm>
#include <ctime> // Для работы с датой и временем
const std::string OUTPUT_SUFFIX = ".output.mp4"; // Суффикс для выходного файла
struct Time {
int hours, minutes;
double seconds;
Time(int h = 0, int m = 0, double s = 0.0) : hours(h), minutes(m), seconds(s) {}
std::string toString() const {
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << hours << ":"
<< std::setw(2) << std::setfill('0') << minutes << ":"
<< std::fixed << std::setprecision(6) << std::setfill('0') << seconds;
return ss.str();
}
bool operator<(const Time& other) const {
if (hours != other.hours) return hours < other.hours;
if (minutes != other.minutes) return minutes < other.minutes;
return seconds < other.seconds;
}
bool operator>(const Time& other) const {
if (hours != other.hours) return hours > other.hours;
if (minutes != other.minutes) return minutes > other.minutes;
return seconds > other.seconds;
}
void subtract(double sec) {
seconds -= sec;
if (seconds < 0) {
seconds += 60;
minutes--;
}
if (minutes < 0) {
minutes += 60;
hours--;
}
if (hours < 0) {
hours = 0;
minutes = 0;
seconds = 0.0;
}
}
};
bool runFFProbe(const std::string& input_file, const std::string& output_file) {
std::string command = "ffprobe -i \"" + input_file + "\" -select_streams v -skip_frame nokey -show_frames -show_entries frame=pkt_pts_time -sexagesimal -print_format csv > \"" + output_file + "\"";
return system(command.c_str()) == 0; // Возвращает true, если команда выполнена успешно
}
bool checkIfFileExists(const std::string& filename) {
std::ifstream file(filename);
return file.good();
}
void formatTimestamps(const std::string& input_file, const std::string& output_file) {
std::ifstream infile(input_file);
std::ofstream outfile(output_file);
std::string line;
while (std::getline(infile, line)) {
size_t comma_pos = line.find(',');
if (comma_pos != std::string::npos) {
// Печатаем значение времени во втором столбце
outfile << line.substr(comma_pos + 1) << std::endl;
}
}
}
std::vector<Time> readKeyframesFromFile(const std::string& filename) {
std::ifstream file(filename);
std::vector<Time> timestamps;
std::string line;
while (std::getline(file, line)) {
std::istringstream ss(line);
int h, m;
double s;
char colon1, colon2;
ss >> h >> colon1 >> m >> colon2 >> s;
if (ss && colon1 == ':' && colon2 == ':') {
timestamps.emplace_back(h, m, s);
}
}
return timestamps;
}
Time findMaxTimeLessThan(const std::string& filename, const Time& user_time) {
std::ifstream file(filename);
std::string line;
Time max_time(0, 0, 0.0);
while (std::getline(file, line)) {
std::istringstream ss(line);
int h, m;
double s;
char colon1, colon2;
ss >> h >> colon1 >> m >> colon2 >> s;
if (ss && colon1 == ':' && colon2 == ':') {
Time current_time(h, m, s);
if (current_time < user_time && current_time > max_time) {
max_time = current_time;
}
}
}
return max_time;
}
// Функция для получения текущей даты и времени в нужном формате
std::string getCurrentDateTimeString() {
std::time_t now = std::time(nullptr);
std::tm* local_time = std::localtime(&now);
std::ostringstream oss;
oss << std::put_time(local_time, "%Y.%m.%d_%H-%M-%S");
return oss.str();
}
// Функция для извлечения расширения файла
std::string getFileExtension(const std::string& filename) {
size_t dot_pos = filename.rfind('.');
if (dot_pos != std::string::npos) {
return filename.substr(dot_pos); // Возвращает все, что после последней точки
}
return ""; // Если точка не найдена, возвращаем пустую строку
}
int main(int argc, char* argv[]) {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <input_file> <time_to_compare> <end_time (optional)>" << std::endl;
return 1;
}
std::string input_file = argv[1];
std::string search_time_str = argv[2];
std::string end_time_str = (argc > 3) ? argv[3] : ""; // Опциональный третий аргумент
// Генерация выходного файла ключевых кадров
std::string keyframe_file = input_file + "_keyframes.txt";
if (!checkIfFileExists(keyframe_file))
{
// Запуск ffprobe для извлечения ключевых кадров
if (!runFFProbe(input_file, keyframe_file)) {
std::cerr << "Error running ffprobe." << std::endl;
return 1;
}
// Создание файла с отформатированными временными метками
std::string formatted_keyframe_file = input_file + "_formatted_keyframes.txt";
formatTimestamps(keyframe_file, formatted_keyframe_file);
// Удаление оригинального файла с ключевыми кадрами
remove(keyframe_file.c_str());
// Переименование отформатированного файла
rename(formatted_keyframe_file.c_str(), keyframe_file.c_str());
}
// Разбор введенного времени пользователем
std::istringstream ss(search_time_str);
int h, m;
double s;
char colon1, colon2;
ss >> h >> colon1 >> m >> colon2 >> s;
Time user_time(h, m, s);
// Поиск наибольшего значения временной метки, меньшего чем user_time
Time max_time = findMaxTimeLessThan(keyframe_file, user_time);
// Вывод результата
if (max_time.seconds > 0) {
std::cout << "The largest time less than " << user_time.toString() << " is " << max_time.toString() << std::endl;
max_time.subtract(0.1); // Вычитаем 0.1 секунды
std::cout << "The time after subtracting 0:0:0.1 is " << max_time.toString() << std::endl;
// Формирование команды ffmpeg
// std::string current_datetime_suffix = getCurrentDateTimeString();
// std::string output_file = input_file + "." + current_datetime_suffix + ".mp4";
// Извлечение расширения входного файла
std::string file_extension = getFileExtension(input_file);
std::string current_datetime_suffix = getCurrentDateTimeString();
// Создание имени выходного файла с учетом расширения
std::string output_file = input_file.substr(0, input_file.size() - file_extension.size()) + "." + current_datetime_suffix + file_extension;
// Формирование команды ffmpeg
std::string command = "ffmpeg -i \"" + input_file + "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -ss " +
max_time.toString() + (end_time_str.empty() ? " " : (" -to " + end_time_str) ) +
" -c copy \"" + output_file + "\"";
// Выполнение команды ffmpeg
if (system(command.c_str()) != 0) {
std::cerr << "Error running ffmpeg." << std::endl;
return 1;
}
} else {
std::cout << "No time found less than " << user_time.toString() << "." << std::endl;
}
return 0;
}
Код: Выделить всё
# Определяем компилятор и флаги компиляции
CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra
# Основной целевой файл
TARGET = splitter
# Исходные файлы
SRCS = splitter.cpp # Замените 'main.cpp' на имя вашего файла с кодом
# Объектные файлы
OBJS = $(SRCS:.cpp=.o)
# Правило по умолчанию для сборки
all: $(TARGET)
# Линковка объекта в исполняемый файл
$(TARGET): $(OBJS)
$(CXX) $(OBJS) -o $(TARGET)
# Правило для компиляции исходников в объектные файлы
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
# Правило для очистки
clean:
rm -f $(OBJS) $(TARGET)
.PHONY: all clean
Код: Выделить всё
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdlib> // Для system()
#include <algorithm>
#include <ctime> // Для работы с датой и временем
class Time {
private:
int hours, minutes;
double seconds;
public:
Time(int h = 0, int m = 0, double s = 0.0) : hours(h), minutes(m), seconds(s) {}
std::string toString() const {
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << hours << ":"
<< std::setw(2) << std::setfill('0') << minutes << ":"
<< std::fixed << std::setprecision(6) << std::setfill('0') << seconds;
return ss.str();
}
bool operator<(const Time& other) const {
return std::tie(hours, minutes, seconds) < std::tie(other.hours, other.minutes, other.seconds);
}
bool operator>(const Time& other) const {
return std::tie(hours, minutes, seconds) > std::tie(other.hours, other.minutes, other.seconds);
}
void subtract(double sec) {
seconds -= sec;
while (seconds < 0) {
seconds += 60;
minutes--;
}
while (minutes < 0) {
minutes += 60;
hours--;
}
if (hours < 0) {
hours = minutes = 0;
seconds = 0.0;
}
}
// Добавим метод для проверки валидности времени
bool isValid() const {
return (hours >= 0 && minutes >= 0 && seconds >= 0);
}
// Метод для доступа к полю seconds
double getSeconds() const {
return seconds;
}
};
class FrameExtractor {
public:
static bool runFFProbe(const std::string& input_file, const std::string& output_file) {
std::string command = "ffprobe -i \"" + input_file + "\" -select_streams v -skip_frame nokey -show_frames "
"-show_entries frame=pkt_pts_time -sexagesimal -print_format csv > \"" + output_file + "\"";
return system(command.c_str()) == 0; // Возвращает true, если команда выполнена успешно
}
static void formatTimestamps(const std::string& input_file, const std::string& output_file) {
std::ifstream infile(input_file);
std::ofstream outfile(output_file);
std::string line;
while (std::getline(infile, line)) {
size_t comma_pos = line.find(',');
if (comma_pos != std::string::npos) {
outfile << line.substr(comma_pos + 1) << std::endl; // Печатаем значение времени во втором столбце
}
}
}
};
class TimeUtils {
public:
static std::string getCurrentDateTimeString() {
std::time_t now = std::time(nullptr);
std::tm* local_time = std::localtime(&now);
std::ostringstream oss;
oss << std::put_time(local_time, "%Y.%m.%d_%H-%M-%S");
return oss.str();
}
static std::string getFileExtension(const std::string& filename) {
size_t dot_pos = filename.rfind('.');
return (dot_pos != std::string::npos) ? filename.substr(dot_pos) : ""; // Возвращает все, что после последней точки
}
};
class TimestampFileParser {
public:
static std::vector<Time> readKeyframesFromFile(const std::string& filename) {
std::ifstream file(filename);
std::vector<Time> timestamps;
std::string line;
while (std::getline(file, line)) {
Time time = parseTime(line);
if (time.isValid()) {
timestamps.push_back(time);
}
}
return timestamps;
}
static Time findMaxTimeLessThan(const std::vector<Time>& timestamps, const Time& user_time) {
Time max_time;
for (const auto& current_time : timestamps) {
if (current_time < user_time && current_time > max_time) {
max_time = current_time;
}
}
return max_time;
}
private:
static Time parseTime(const std::string& time_string) {
int h, m;
double s;
char colon1, colon2;
std::istringstream ss(time_string);
ss >> h >> colon1 >> m >> colon2 >> s;
if (ss && colon1 == ':' && colon2 == ':') {
return Time(h, m, s);
}
return Time(); // Возвращаем время по умолчанию (0, 0, 0)
}
};
class Application {
private:
std::string input_file;
std::string keyframe_file;
public:
Application(const std::string& file) : input_file(file) {
keyframe_file = input_file + "_keyframes.txt";
}
void process(const std::string& search_time_str, const std::string& end_time_str) {
if (!checkIfFileExists(keyframe_file)) {
extractKeyframes();
}
Time user_time = parseSearchTime(search_time_str);
auto timestamps = TimestampFileParser::readKeyframesFromFile(keyframe_file);
Time max_time = TimestampFileParser::findMaxTimeLessThan(timestamps, user_time);
if (max_time.getSeconds() > 0) { // Используем метод getSeconds()
handleFoundTime(max_time, end_time_str);
} else {
std::cout << "No time found less than " << user_time.toString() << "." << std::endl;
}
}
private:
void extractKeyframes() {
std::string formatted_keyframe_file = input_file + "_formatted_keyframes.txt";
if (!FrameExtractor::runFFProbe(input_file, keyframe_file)) {
throw std::runtime_error("Error running ffprobe.");
}
FrameExtractor::formatTimestamps(keyframe_file, formatted_keyframe_file);
// Удаляем оригинальный файл с ключевыми кадрами
remove(keyframe_file.c_str());
// Переименовываем отформатированный файл
rename(formatted_keyframe_file.c_str(), keyframe_file.c_str());
}
Time parseSearchTime(const std::string& search_time_str) {
int h, m;
double s;
char colon1, colon2;
std::istringstream ss(search_time_str);
ss >> h >> colon1 >> m >> colon2 >> s;
return Time(h, m, s);
}
void handleFoundTime(Time& max_time, const std::string& end_time_str) {
max_time.subtract(0.1); // Вычитаем 0.1 секунды
std::string output_file = generateOutputFilename();
std::string command = buildFFmpegCommand(max_time, end_time_str, output_file);
if (system(command.c_str()) != 0) {
throw std::runtime_error("Error running ffmpeg.");
}
std::cout << "The largest time less than " << max_time.toString()
<< " is " << max_time.toString() << std::endl;
}
std::string generateOutputFilename() {
std::string file_extension = TimeUtils::getFileExtension(input_file);
std::string current_datetime_suffix = TimeUtils::getCurrentDateTimeString();
return input_file.substr(0, input_file.size() - file_extension.size())
+ "." + current_datetime_suffix + file_extension;
}
std::string buildFFmpegCommand(const Time& max_time, const std::string& end_time_str, const std::string& output_file) {
return "ffmpeg -i \"" + input_file + "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -ss "
+ max_time.toString() + (end_time_str.empty() ? "" : " -to " + end_time_str) + " -c copy \"" + output_file + "\"";
}
bool checkIfFileExists(const std::string& filename) {
std::ifstream file(filename);
return file.good();
}
};
int main(int argc, char* argv[]) {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <input_file> <time_to_compare> <end_time (optional)>" << std::endl;
return 1;
}
try {
std::string input_file = argv[1];
std::string search_time_str = argv[2];
std::string end_time_str = (argc > 3) ? argv[3] : ""; // Опциональный третий аргумент
Application app(input_file);
app.process(search_time_str, end_time_str);
} catch (const std::runtime_error& e) {
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
Код: Выделить всё
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdlib> // Для system()
#include <algorithm>
#include <ctime> // Для работы с датой и временем
class Time {
private:
int hours, minutes;
double seconds;
public:
Time(int h = 0, int m = 0, double s = 0.0) : hours(h), minutes(m), seconds(s) {}
std::string toString() const {
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << hours << ":"
<< std::setw(2) << std::setfill('0') << minutes << ":"
<< std::fixed << std::setprecision(6) << std::setfill('0') << seconds;
return ss.str();
}
bool operator<(const Time& other) const {
return std::tie(hours, minutes, seconds) < std::tie(other.hours, other.minutes, other.seconds);
}
bool operator>(const Time& other) const {
return std::tie(hours, minutes, seconds) > std::tie(other.hours, other.minutes, other.seconds);
}
void subtract(double sec) {
seconds -= sec;
while (seconds < 0) {
seconds += 60;
minutes--;
}
while (minutes < 0) {
minutes += 60;
hours--;
}
if (hours < 0) {
hours = minutes = 0;
seconds = 0.0;
}
}
// Добавим метод для проверки валидности времени
bool isValid() const {
return (hours >= 0 && minutes >= 0 && seconds >= 0);
}
// Метод для доступа к полю seconds
double getSeconds() const {
return seconds;
}
};
class FrameExtractor {
public:
static bool runFFProbe(const std::string& input_file, const std::string& output_file) {
std::string command = "ffprobe -i \"" + input_file + "\" -select_streams v -skip_frame nokey -show_frames "
"-show_entries frame=pkt_pts_time -sexagesimal -print_format csv > \"" + output_file + "\"";
return system(command.c_str()) == 0; // Возвращает true, если команда выполнена успешно
}
static void formatTimestamps(const std::string& input_file, const std::string& output_file) {
std::ifstream infile(input_file);
std::ofstream outfile(output_file);
std::string line;
while (std::getline(infile, line)) {
size_t comma_pos = line.find(',');
if (comma_pos != std::string::npos) {
outfile << line.substr(comma_pos + 1) << std::endl; // Печатаем значение времени во втором столбце
}
}
}
};
class TimeUtils {
public:
static std::string getCurrentDateTimeString() {
std::time_t now = std::time(nullptr);
std::tm* local_time = std::localtime(&now);
std::ostringstream oss;
oss << std::put_time(local_time, "%Y.%m.%d_%H-%M-%S");
return oss.str();
}
static std::string getFileExtension(const std::string& filename) {
size_t dot_pos = filename.rfind('.');
return (dot_pos != std::string::npos) ? filename.substr(dot_pos) : ""; // Возвращает все, что после последней точки
}
};
class TimestampFileParser {
public:
static std::vector<Time> readKeyframesFromFile(const std::string& filename) {
std::ifstream file(filename);
std::vector<Time> timestamps;
std::string line;
while (std::getline(file, line)) {
Time time = parseTime(line);
if (time.isValid()) {
timestamps.push_back(time);
}
}
return timestamps;
}
static Time findMaxTimeLessThan(const std::vector<Time>& timestamps, const Time& user_time) {
Time max_time;
for (const auto& current_time : timestamps) {
if (current_time < user_time && current_time > max_time) {
max_time = current_time;
}
}
return max_time;
}
private:
static Time parseTime(const std::string& time_string) {
int h, m;
double s;
char colon1, colon2;
std::istringstream ss(time_string);
ss >> h >> colon1 >> m >> colon2 >> s;
if (ss && colon1 == ':' && colon2 == ':') {
return Time(h, m, s);
}
return Time(); // Возвращаем время по умолчанию (0, 0, 0)
}
};
class Application {
private:
std::string input_file;
std::string keyframe_file;
public:
Application(const std::string& file) : input_file(file) {
keyframe_file = input_file + "_keyframes.txt";
}
void process(const std::string& search_time_str, const std::string& end_time_str) {
if (search_time_str == "0") {
// Если second argument is "0", просто вызываем ffmpeg без дополнительных операций
generateAndRunFFmpegCommand(end_time_str);
return; // Возвращаемся, чтобы не производить дальнейшие операции
}
if (!checkIfFileExists(keyframe_file)) {
extractKeyframes();
}
Time user_time = parseSearchTime(search_time_str);
auto timestamps = TimestampFileParser::readKeyframesFromFile(keyframe_file);
Time max_time = TimestampFileParser::findMaxTimeLessThan(timestamps, user_time);
if (max_time.getSeconds() > 0) {
handleFoundTime(max_time, end_time_str);
} else {
std::cout << "No time found less than " << user_time.toString() << "." << std::endl;
}
}
private:
void extractKeyframes() {
std::string formatted_keyframe_file = input_file + "_formatted_keyframes.txt";
if (!FrameExtractor::runFFProbe(input_file, keyframe_file)) {
throw std::runtime_error("Error running ffprobe.");
}
FrameExtractor::formatTimestamps(keyframe_file, formatted_keyframe_file);
remove(keyframe_file.c_str());
rename(formatted_keyframe_file.c_str(), keyframe_file.c_str());
}
Time parseSearchTime(const std::string& search_time_str) {
int h, m;
double s;
char colon1, colon2;
std::istringstream ss(search_time_str);
ss >> h >> colon1 >> m >> colon2 >> s;
return Time(h, m, s);
}
void handleFoundTime(Time& max_time, const std::string& end_time_str) {
max_time.subtract(0.1);
std::string output_file = generateOutputFilename();
std::string command = buildFFmpegCommand(max_time, end_time_str, output_file);
if (system(command.c_str()) != 0) {
throw std::runtime_error("Error running ffmpeg.");
}
std::cout << "The largest time less than " << max_time.toString()
<< " is " << max_time.toString() << std::endl;
}
void generateAndRunFFmpegCommand(const std::string& end_time_str) {
std::string output_file = generateOutputFilename();
std::string command = "ffmpeg -i \"" + input_file + "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -c copy \"" + output_file + "\"";
if (!end_time_str.empty()) {
command.insert(command.find("-c copy") - 1, " -to " + end_time_str); // Добавление параметра -to
}
if (system(command.c_str()) != 0) {
throw std::runtime_error("Error running ffmpeg.");
}
std::cout << "Command executed successfully: " << command << std::endl;
}
std::string generateOutputFilename() {
std::string file_extension = TimeUtils::getFileExtension(input_file);
std::string current_datetime_suffix = TimeUtils::getCurrentDateTimeString();
return input_file.substr(0, input_file.size() - file_extension.size())
+ "." + current_datetime_suffix + file_extension;
}
std::string buildFFmpegCommand(const Time& max_time, const std::string& end_time_str, const std::string& output_file) {
return "ffmpeg -i \"" + input_file + "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -ss "
+ max_time.toString() + (end_time_str.empty() ? "" : " -to " + end_time_str) + " -c copy \"" + output_file + "\"";
}
bool checkIfFileExists(const std::string& filename) {
std::ifstream file(filename);
return file.good();
}
};
int main(int argc, char* argv[]) {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <input_file> <time_to_compare> <end_time (optional)>" << std::endl;
return 1;
}
try {
std::string input_file = argv[1];
std::string search_time_str = argv[2];
std::string end_time_str = (argc > 3) ? argv[3] : "";
Application app(input_file);
app.process(search_time_str, end_time_str);
} catch (const std::runtime_error& e) {
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
Код: Выделить всё
# Определяем компилятор и флаги компиляции
CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra
# Основной целевой файл
TARGET = splitter
# Исходные файлы
SRCS = splitter3.cpp # Замените 'main.cpp' на имя вашего файла с кодом
# Объектные файлы
OBJS = $(SRCS:.cpp=.o)
# Правило по умолчанию для сборки
all: $(TARGET)
# Линковка объекта в исполняемый файл
$(TARGET): $(OBJS)
$(CXX) $(OBJS) -o $(TARGET)
# Правило для компиляции исходников в объектные файлы
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
# Правило для очистки
clean:
rm -f $(OBJS) $(TARGET)
.PHONY: all clean