Whisper: create base plugin
GitLab: #576
Change-Id: Icae9e8b0653aa7aa7987774cea80d1720673edc0
diff --git a/.tx/config b/.tx/config
index 3be6740..db52030 100755
--- a/.tx/config
+++ b/.tx/config
@@ -25,3 +25,9 @@
type = KEYVALUEJSON
minimum_perc = 0
+[o:savoirfairelinux:p:jami:r:plugin_whispertranscript]
+file_filter = WhisperTranscript/data/locale/WhisperTranscript_<lang>.json
+source_file = WhisperTranscript/data/locale/WhisperTranscript_en.json
+type = KEYVALUEJSON
+minimum_perc = 0
+
diff --git a/AudioFilter/FilterMediaHandler.cpp b/AudioFilter/FilterMediaHandler.cpp
index 02a0e06..cb18408 100644
--- a/AudioFilter/FilterMediaHandler.cpp
+++ b/AudioFilter/FilterMediaHandler.cpp
@@ -57,12 +57,12 @@
oss << "preferredStreamDirection " << preferredStreamDirection << std::endl;
if (data.type == StreamType::audio && !data.direction
&& data.direction == preferredStreamDirection) {
- subject->attach(mAS_.get()); // your image
+ subject->attach(mAS_.get()); // your audio
oss << "got my sent audio attached" << std::endl;
attached_ = '1';
} else if (data.type == StreamType::audio && data.direction
&& data.direction == preferredStreamDirection) {
- subject->attach(mAS_.get()); // the image you receive from others on the call
+ subject->attach(mAS_.get()); // the audio you receive from others on the call
oss << "got received audio attached" << std::endl;
attached_ = '1';
}
diff --git a/GreenScreen/CMakeLists.txt b/GreenScreen/CMakeLists.txt
index d4677ed..6401be9 100644
--- a/GreenScreen/CMakeLists.txt
+++ b/GreenScreen/CMakeLists.txt
@@ -118,6 +118,7 @@
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/zlib ${CONTRIB_PATH}/src/zlib
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/ffmpeg/ ${CONTRIB_PATH}/src/ffmpeg
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/../contrib/yaml-cpp ${CONTRIB_PATH}/src/yaml-cpp
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/../contrib/mp3lame ${CONTRIB_PATH}/src/mp3lame
COMMAND python ${DAEMON}/compat/msvc/winmake.py -fb yaml-cpp
COMMAND python ${DAEMON}/compat/msvc/winmake.py -fb zlib
COMMAND python ${DAEMON}/compat/msvc/winmake.py -fb ffmpeg
@@ -130,6 +131,7 @@
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/testPreferences.yml ${PROJECT_BINARY_DIR}/
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/sample.mp4 ${PROJECT_BINARY_DIR}/
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/Debug
COMMAND ${CMAKE_COMMAND} -E copy ${ONNX_DIR}/onnxruntime.lib ${PROJECT_BINARY_DIR}/Debug
COMMAND ${CMAKE_COMMAND} -E copy ${ONNX_DIR}/onnxruntime.dll ${PROJECT_BINARY_DIR}/Debug
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/data/model
diff --git a/GreenScreen/videoSubscriber.h b/GreenScreen/videoSubscriber.h
index df7edd3..ba8f485 100644
--- a/GreenScreen/videoSubscriber.h
+++ b/GreenScreen/videoSubscriber.h
@@ -33,15 +33,15 @@
namespace jami {
-class VideoSubscriber : public jami::Observer<AVFrame*>
+class VideoSubscriber : public Observer<AVFrame*>
{
public:
VideoSubscriber(const std::string& model, bool acc = false);
~VideoSubscriber();
- virtual void update(jami::Observable<AVFrame*>*, AVFrame* const&) override;
- virtual void attached(jami::Observable<AVFrame*>*) override;
- virtual void detached(jami::Observable<AVFrame*>*) override;
+ virtual void update(Observable<AVFrame*>*, AVFrame* const&) override;
+ virtual void attached(Observable<AVFrame*>*) override;
+ virtual void detached(Observable<AVFrame*>*) override;
void detach();
void stop();
diff --git a/HelloWorld/CenterCircleVideoSubscriber.h b/HelloWorld/CenterCircleVideoSubscriber.h
index 29481f7..f8f11a5 100644
--- a/HelloWorld/CenterCircleVideoSubscriber.h
+++ b/HelloWorld/CenterCircleVideoSubscriber.h
@@ -28,15 +28,15 @@
namespace jami {
-class CenterCircleVideoSubscriber : public jami::Observer<AVFrame*>
+class CenterCircleVideoSubscriber : public Observer<AVFrame*>
{
public:
CenterCircleVideoSubscriber(const std::string& dataPath);
~CenterCircleVideoSubscriber();
- virtual void update(jami::Observable<AVFrame*>*, AVFrame* const&) override;
- virtual void attached(jami::Observable<AVFrame*>*) override;
- virtual void detached(jami::Observable<AVFrame*>*) override;
+ virtual void update(Observable<AVFrame*>*, AVFrame* const&) override;
+ virtual void attached(Observable<AVFrame*>*) override;
+ virtual void detached(Observable<AVFrame*>*) override;
void detach();
diff --git a/HelloWorld/CoinCircleVideoSubscriber.h b/HelloWorld/CoinCircleVideoSubscriber.h
index 373f0b8..c355cab 100644
--- a/HelloWorld/CoinCircleVideoSubscriber.h
+++ b/HelloWorld/CoinCircleVideoSubscriber.h
@@ -28,15 +28,15 @@
namespace jami {
-class CoinCircleVideoSubscriber : public jami::Observer<AVFrame*>
+class CoinCircleVideoSubscriber : public Observer<AVFrame*>
{
public:
CoinCircleVideoSubscriber(const std::string& dataPath);
~CoinCircleVideoSubscriber();
- virtual void update(jami::Observable<AVFrame*>*, AVFrame* const&) override;
- virtual void attached(jami::Observable<AVFrame*>*) override;
- virtual void detached(jami::Observable<AVFrame*>*) override;
+ virtual void update(Observable<AVFrame*>*, AVFrame* const&) override;
+ virtual void attached(Observable<AVFrame*>*) override;
+ virtual void detached(Observable<AVFrame*>*) override;
void detach();
diff --git a/SDK/Templates/build.sh b/SDK/Templates/build.sh
index 6c23c16..7f61802 100644
--- a/SDK/Templates/build.sh
+++ b/SDK/Templates/build.sh
@@ -2,7 +2,7 @@
# Build the plugin for the project
set -e
export OSTYPE
-ARCH=$(arch)
+ARCH=$(uname -m)
EXTRAPATH=''
# Flags:
@@ -48,17 +48,24 @@
if [ "${PLATFORM}" = "linux-gnu" ] || [ "${PLATFORM}" = "redhat-linux" ]
then
- python3 ./../SDK/jplManipulation.py --preassemble --plugin=${PLUGIN_NAME}
-
CONTRIB_PLATFORM_CURT=${ARCH}
CONTRIB_PLATFORM=${CONTRIB_PLATFORM_CURT}-${PLATFORM}
+ if [ ${DEBUG} ]; then
+ OUTPUT="${PLUGIN_NAME}"
+ CLANG_OPTS="-g -fsanitize=address"
+ EXTRA_DEBUG_LIBRARIES="-lyaml-cpp"
+ EXTRA_DEFINES="-D__DEBUG__"
+ else
+ python3 ./../SDK/jplManipulation.py --preassemble --plugin=${PLUGIN_NAME}
+ CLANG_OPTS="-O3 -shared"
+ OUTPUT="build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}"
+ fi
+
# Compile
- clang++ -std=c++17 -shared -fPIC \
+ clang++ -std=c++17 -fPIC ${CLANG_OPTS} \
-Wl,-Bsymbolic,-rpath,"\${ORIGIN}" \
-Wall -Wextra \
- -Wno-unused-variable \
- -Wno-unused-function \
-Wno-unused-parameter \
-I"." \
-I"${DAEMON_SRC}" \
diff --git a/SDK/Templates/genericMediaHandler.cpp b/SDK/Templates/genericMediaHandler.cpp
index 109ec71..825cb1c 100644
--- a/SDK/Templates/genericMediaHandler.cpp
+++ b/SDK/Templates/genericMediaHandler.cpp
@@ -32,12 +32,12 @@
oss << "preferredStreamDirection " << preferredStreamDirection << std::endl;
if (data.type == StreamType::DataType && !data.direction
&& data.direction == preferredStreamDirection) {
- subject->attach(mediaSubscriber_.get()); // your image
+ subject->attach(mediaSubscriber_.get()); // your media
oss << "got my sent image attached" << std::endl;
attached_ = "1";
} else if (data.type == StreamType::DataType && data.direction
&& data.direction == preferredStreamDirection) {
- subject->attach(mediaSubscriber_.get()); // the image you receive from others on the call
+ subject->attach(mediaSubscriber_.get()); // the media you receive from others on the call
oss << "got received image attached" << std::endl;
attached_ = "1";
}
diff --git a/SDK/Templates/genericMediaHandler.h b/SDK/Templates/genericMediaHandler.h
index 2e806b9..50409a7 100644
--- a/SDK/Templates/genericMediaHandler.h
+++ b/SDK/Templates/genericMediaHandler.h
@@ -7,11 +7,11 @@
#include "plugin/jamiplugin.h"
#include "plugin/mediahandler.h"
-using avSubjectPtr = std::weak_ptr<jami::Observable<AVFrame*>>;
-
namespace jami {
-class GENERICMediaHandler : public jami::CallMediaHandler
+using avSubjectPtr = std::weak_ptr<Observable<AVFrame*>>;
+
+class GENERICMediaHandler : public CallMediaHandler
{
public:
GENERICMediaHandler(std::map<std::string, std::string>&& preferences, std::string&& dataPath);
diff --git a/SDK/Templates/genericMediaSubscriber.h b/SDK/Templates/genericMediaSubscriber.h
index c716844..2e86975 100644
--- a/SDK/Templates/genericMediaSubscriber.h
+++ b/SDK/Templates/genericMediaSubscriber.h
@@ -11,15 +11,15 @@
namespace jami {
-class GENERICDATATYPESubscriber : public jami::Observer<AVFrame*>
+class GENERICDATATYPESubscriber : public Observer<AVFrame*>
{
public:
GENERICDATATYPESubscriber(const std::string& dataPath);
~GENERICDATATYPESubscriber();
- virtual void update(jami::Observable<AVFrame*>*, AVFrame* const&) override;
- virtual void attached(jami::Observable<AVFrame*>*) override;
- virtual void detached(jami::Observable<AVFrame*>*) override;
+ virtual void update(Observable<AVFrame*>*, AVFrame* const&) override;
+ virtual void attached(Observable<AVFrame*>*) override;
+ virtual void detached(Observable<AVFrame*>*) override;
void detach();
diff --git a/SDK/Templates/main.cpp b/SDK/Templates/main.cpp
index abca25b..436601e 100644
--- a/SDK/Templates/main.cpp
+++ b/SDK/Templates/main.cpp
@@ -8,6 +8,14 @@
----------------
#include "INCLUDESAPI.h"----------------
+
+#ifdef __DEBUG__
+#include <common.h>
+#include <assert.h>
+#include <yaml-cpp/yaml.h>
+#include <fstream>
+#endif
+
#ifdef WIN32
#define EXPORT_PLUGIN __declspec(dllexport)
#else
@@ -49,3 +57,41 @@
return pluginExit;
}
}
+
+#ifdef __DEBUG__
+
+int
+main ()
+{
+ std::cout << "*******************************" << std::endl;
+ std::cout << "** PLUGINNAME Debug Version **" << std::endl;
+ std::cout << "*******************************" << std::endl;
+ std::cout << "Version " << PLUGINNAME_VERSION_MAJOR << "." << PLUGINNAME_VERSION_MINOR << "."
+ << PLUGINNAME_VERSION_PATCH << std::endl << std::endl;
+
+ std::ifstream file;
+ file_utils::openStream(file, "testPreferences.yml");
+
+ assert(file.is_open());
+ YAML::Node node = YAML::Load(file);
+
+ assert(node.IsMap());
+ std::map<std::string, std::map<std::string, std::string>> preferences;
+ preferences["default"] = {};
+ for (const auto& kv : node) {
+ preferences["default"][kv.first.as<std::string>()] = kv.second.as<std::string>();
+ std::cout << "Key: " << kv.first.as<std::string>() << "; Value: " << kv.second.as<std::string>() << std::endl;
+ }
+
+#ifdef _WIN32
+ std::string dataPath = "../data";
+#else
+ std::string dataPath = "data";
+#endif
+
+
+
+ return 0;
+}
+
+#endif
diff --git a/TensorflowSegmentation/build.sh b/TensorflowSegmentation/build.sh
index ddeb354..1c35673 100755
--- a/TensorflowSegmentation/build.sh
+++ b/TensorflowSegmentation/build.sh
@@ -2,7 +2,7 @@
# Build the plugin for the project
set -e
export OSTYPE
-ARCH=$(arch)
+ARCH=$(uname -m)
EXTRAPATH=''
# Flags:
diff --git a/TensorflowSegmentation/videoSubscriber.h b/TensorflowSegmentation/videoSubscriber.h
index 8f37c54..51949f2 100644
--- a/TensorflowSegmentation/videoSubscriber.h
+++ b/TensorflowSegmentation/videoSubscriber.h
@@ -51,15 +51,15 @@
cv::Mat predictionsResizedFrameRGB;
};
-class VideoSubscriber : public jami::Observer<AVFrame*>
+class VideoSubscriber : public Observer<AVFrame*>
{
public:
VideoSubscriber(const std::string& dataPath);
~VideoSubscriber();
- virtual void update(jami::Observable<AVFrame*>*, AVFrame* const&) override;
- virtual void attached(jami::Observable<AVFrame*>*) override;
- virtual void detached(jami::Observable<AVFrame*>*) override;
+ virtual void update(Observable<AVFrame*>*, AVFrame* const&) override;
+ virtual void attached(Observable<AVFrame*>*) override;
+ virtual void detached(Observable<AVFrame*>*) override;
void detach();
void stop();
diff --git a/TestSuite/VideoSubscriberTester.h b/TestSuite/VideoSubscriberTester.h
index 49d5ca7..794637e 100644
--- a/TestSuite/VideoSubscriberTester.h
+++ b/TestSuite/VideoSubscriberTester.h
@@ -27,15 +27,15 @@
namespace jami {
-class VideoSubscriberTester : public jami::Observer<AVFrame*>
+class VideoSubscriberTester : public Observer<AVFrame*>
{
public:
VideoSubscriberTester() {}
~VideoSubscriberTester();
- virtual void update(jami::Observable<AVFrame*>*, AVFrame* const&) override {}
- virtual void attached(jami::Observable<AVFrame*>*) override;
- virtual void detached(jami::Observable<AVFrame*>*) override;
+ virtual void update(Observable<AVFrame*>*, AVFrame* const&) override {}
+ virtual void attached(Observable<AVFrame*>*) override;
+ virtual void detached(Observable<AVFrame*>*) override;
void detach();
diff --git a/WaterMark/CMakeLists.txt b/WaterMark/CMakeLists.txt
index aff84f7..1071671 100644
--- a/WaterMark/CMakeLists.txt
+++ b/WaterMark/CMakeLists.txt
@@ -99,6 +99,7 @@
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/zlib ${CONTRIB_PATH}/src/zlib
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/../contrib/freetype ${CONTRIB_PATH}/src/freetype
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/../contrib/mp3lame ${CONTRIB_PATH}/src/mp3lame
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/ffmpeg/ ${CONTRIB_PATH}/src/ffmpeg
COMMAND python ${DAEMON}/compat/msvc/winmake.py -fb zlib
COMMAND python ${DAEMON}/compat/msvc/winmake.py -fb freetype
diff --git a/WaterMark/WatermarkVideoSubscriber.h b/WaterMark/WatermarkVideoSubscriber.h
index 311d933..db0417a 100644
--- a/WaterMark/WatermarkVideoSubscriber.h
+++ b/WaterMark/WatermarkVideoSubscriber.h
@@ -48,15 +48,15 @@
SHOWINFOS,
};
-class WatermarkVideoSubscriber : public jami::Observer<AVFrame*>
+class WatermarkVideoSubscriber : public Observer<AVFrame*>
{
public:
WatermarkVideoSubscriber(const std::string& dataPath);
~WatermarkVideoSubscriber();
- virtual void update(jami::Observable<AVFrame*>*, AVFrame* const&) override;
- virtual void attached(jami::Observable<AVFrame*>*) override;
- virtual void detached(jami::Observable<AVFrame*>*) override;
+ virtual void update(Observable<AVFrame*>*, AVFrame* const&) override;
+ virtual void attached(Observable<AVFrame*>*) override;
+ virtual void detached(Observable<AVFrame*>*) override;
void detach();
diff --git a/WhisperTranscript/.gitignore b/WhisperTranscript/.gitignore
new file mode 100644
index 0000000..5a3f926
--- /dev/null
+++ b/WhisperTranscript/.gitignore
@@ -0,0 +1,5 @@
+*.mp3
+/WhisperTranscript*
+libonnxruntime.so*
+/libonnxruntime.dylib
+/processed.mp4
diff --git a/WhisperTranscript/CMakeLists.txt b/WhisperTranscript/CMakeLists.txt
new file mode 100644
index 0000000..db5f416
--- /dev/null
+++ b/WhisperTranscript/CMakeLists.txt
@@ -0,0 +1,171 @@
+cmake_minimum_required(VERSION 3.10)
+
+# set the project name
+set (ProjectName WhisperTranscript)
+set (Version 0.0.0)
+
+project(${ProjectName} VERSION ${Version})
+
+set (DAEMON ${PROJECT_SOURCE_DIR}/../../daemon)
+set (JPL_FILE_NAME ${ProjectName}.jpl)
+set (DAEMON_SRC ${DAEMON}/src)
+set (CONTRIB_PATH ${DAEMON}/contrib)
+set (PLUGINS_LIB ${PROJECT_SOURCE_DIR}/../lib)
+set (JPL_DIRECTORY ${PROJECT_BINARY_DIR}/jpl)
+set (LIBS_DIR ${PROJECT_SOURCE_DIR}/../contrib/Libs)
+set (ONNX_DIR $ENV{PLUGIN_ENV}/onnxruntime)
+
+if(WIN32)
+ message(OS:\ WINDOWS\ ${CMAKE_SYSTEM_PROCESSOR})
+ if (NOT ${CMAKE_CL_64})
+ message( FATAL_ERROR "\nUse CMake only for x64 Windows" )
+ endif()
+ set (CONTRIB_PLATFORM_CURT x64)
+ set (CONTRIB_PLATFORM ${CONTRIB_PLATFORM_CURT}-windows)
+ set (LIBRARY_FILE_NAME ${ProjectName}.dll)
+ set (FFMPEG ${CONTRIB_PATH}/build/ffmpeg/Build/win32/x64)
+else()
+ message( FATAL_ERROR "\nUse CMake only for Windows! For linux or Android (linux host), use our bash scripts." )
+endif()
+
+message(Building:\ ${ProjectName}\ ${Version})
+message(Build\ path:\ ${PROJECT_BINARY_DIR})
+message(JPL\ assembling\ path:\ ${JPL_DIRECTORY})
+message(JPL\ path:\ ${JPL_DIRECTORY}/../../../build/${ProjectName}/${JPL_FILE_NAME})
+
+if(NVIDIA)
+add_definitions(-DNVIDIA)
+set(ONNX_DIR ${ONNX_DIR}/nvidia-gpu)
+message(Provider:\ NVIDIA)
+set(EXTRA_PATH nvidia-gpu)
+else()
+set(ONNX_DIR ${ONNX_DIR}/cpu)
+message(Provider:\ NONE)
+set(EXTRA_PATH cpu)
+endif()
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+if(TESTPROCESS)
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D__DEBUG__ /MT")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /D__DEBUG__ /MT")
+else()
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MT")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
+endif()
+
+set(plugin_SRC main.cpp
+ TranscriptMediaHandler.cpp
+ TranscriptAudioSubscriber.cpp
+ TranscriptVideoSubscriber.cpp
+ Preprocess.cpp
+ ModelProcessor.cpp
+ ./../lib/accel.cpp
+ ./../lib/frameUtils.cpp
+ ./../lib/frameFilter.cpp
+ ./../lib/common.cpp
+ )
+
+set(plugin_HDR TranscriptAudioSubscriber.h
+ TranscriptVideoSubscriber.h
+ TranscriptMediaHandler.h
+ Preprocess.h
+ ModelProcessor.h
+ ./../lib/frameUtils.h
+ ./../lib/frameFilter.h
+ ./../lib/common.h
+ ./../lib/pluglog.h
+ ./../lib/mediaStream.h
+ ./../lib/audioFormat.h
+ )
+
+if(TESTPROCESS)
+ add_executable(${ProjectName} ${plugin_SRC}
+ ${plugin_HDR}
+ )
+else()
+ add_library(${ProjectName} SHARED ${plugin_SRC}
+ ${plugin_HDR}
+ )
+endif()
+
+target_include_directories(${ProjectName} PUBLIC ${PROJECT_BINARY_DIR}
+ ${PROJECT_SOURCE_DIR}
+ ${PLUGINS_LIB}
+ ${DAEMON_SRC}
+ ${CONTRIB_PATH}
+ ${CONTRIB_PATH}/build/fmt/include
+ ${FFMPEG}/include
+ ${ONNX_DIR}/../include/session
+ ${ONNX_DIR}/../include/providers/cuda
+ ${CONTRIB_PATH}/build/yaml-cpp/include
+ )
+target_link_directories(${ProjectName} PUBLIC ${CONTRIB_PATH}
+ ${CONTRIB_PATH}/build/fmt/msvc/Release
+ ${FFMPEG}/lib
+ ${ONNX_DIR}
+ ${CONTRIB_PATH}/msvc/lib/x64
+ ${CONTRIB_PATH}/build/fmt/msvc/Release
+ ${CONTRIB_PATH}/build/yaml-cpp/msvc/Release
+ )
+
+target_link_libraries(${ProjectName} PUBLIC libyaml-cppmd libavfilter libswscale libswresample libavformat
+ libavcodec libavutil libvpx libx264 libopus libmfx
+ libzlib ws2_32 Bcrypt Secur32 onnxruntime msvcrt)
+
+add_custom_command(
+ TARGET ${ProjectName}
+ PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/zlib ${CONTRIB_PATH}/src/zlib
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/ffmpeg/ ${CONTRIB_PATH}/src/ffmpeg
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/../contrib/yaml-cpp ${CONTRIB_PATH}/src/yaml-cpp
+ COMMAND python ${DAEMON}/compat/msvc/winmake.py -fb yaml-cpp
+ COMMAND python ${DAEMON}/compat/msvc/winmake.py -fb zlib
+ COMMAND python ${DAEMON}/compat/msvc/winmake.py -fb ffmpeg
+ COMMAND cd ${CONTRIB_PATH}/src/
+ COMMAND git checkout *
+)
+
+
+if(TESTPROCESS)
+ add_custom_command(
+ TARGET ${ProjectName}
+ PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/testPreferences.yml ${PROJECT_BINARY_DIR}/
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/jfk.wav ${PROJECT_BINARY_DIR}/
+ COMMAND ${CMAKE_COMMAND} -E copy ${ONNX_DIR}/onnxruntime.lib ${PROJECT_BINARY_DIR}/Debug
+ COMMAND ${CMAKE_COMMAND} -E copy ${ONNX_DIR}/onnxruntime.dll ${PROJECT_BINARY_DIR}/Debug
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/modelSRC/mModelEncoder.onnx ${PROJECT_SOURCE_DIR}/data/assets
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/modelSRC/mModelDecoder.onnx ${PROJECT_SOURCE_DIR}/data/assets
+ )
+else()
+ add_custom_command(
+ TARGET ${ProjectName}
+ PRE_BUILD
+ COMMAND python ${PROJECT_SOURCE_DIR}/../SDK/jplManipulation.py --preassemble --plugin=${ProjectName}
+ COMMAND ${CMAKE_COMMAND} -E copy ${ONNX_DIR}/onnxruntime.lib ${JPL_DIRECTORY}/lib/${CONTRIB_PLATFORM}
+ COMMAND ${CMAKE_COMMAND} -E copy ${ONNX_DIR}/onnxruntime.dll ${JPL_DIRECTORY}/lib/${CONTRIB_PLATFORM}
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/modelSRC/mModelEncoder.onnx ${JPL_DIRECTORY}/data/assets
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/modelSRC/mModelDecoder.onnx ${JPL_DIRECTORY}/data/assets
+ COMMENT "Assembling Plugin files"
+ )
+ if(NVIDIA)
+ add_custom_command(
+ TARGET ${ProjectName}
+ PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${ONNX_DIR}/onnxruntime_providers_shared.lib ${JPL_DIRECTORY}/lib/${CONTRIB_PLATFORM}
+ COMMAND ${CMAKE_COMMAND} -E copy ${ONNX_DIR}/onnxruntime_providers_shared.dll ${JPL_DIRECTORY}/lib/${CONTRIB_PLATFORM}
+ COMMAND ${CMAKE_COMMAND} -E copy ${ONNX_DIR}/onnxruntime_providers_cuda.lib ${JPL_DIRECTORY}/lib/${CONTRIB_PLATFORM}
+ COMMAND ${CMAKE_COMMAND} -E copy ${ONNX_DIR}/onnxruntime_providers_cuda.dll ${JPL_DIRECTORY}/lib/${CONTRIB_PLATFORM}
+ )
+ endif()
+ add_custom_command(
+ TARGET ${ProjectName}
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/Release/${ProjectName}.lib ${JPL_DIRECTORY}/lib/${CONTRIB_PLATFORM}
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/Release/${LIBRARY_FILE_NAME} ${JPL_DIRECTORY}/lib/${CONTRIB_PLATFORM}
+ COMMAND python ${PROJECT_SOURCE_DIR}/../SDK/jplManipulation.py --assemble --plugin=${ProjectName} --extraPath=${EXTRA_PATH}
+ COMMENT "Generating JPL archive"
+ )
+endif()
diff --git a/WhisperTranscript/ModelProcessor.cpp b/WhisperTranscript/ModelProcessor.cpp
new file mode 100644
index 0000000..6c0a7b8
--- /dev/null
+++ b/WhisperTranscript/ModelProcessor.cpp
@@ -0,0 +1,323 @@
+/**
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#include "ModelProcessor.h"
+
+#include <pluglog.h>
+#include <common.h>
+
+const char sep = separator();
+
+const std::string TAG = "Transcript";
+
+namespace jami {
+
+ModelProcessor::ModelProcessor(const std::string& path, bool acc)
+{
+ loadTokens(path + "/assets/tokenizer.bin", vocab_);
+
+#ifdef __ANDROID__
+ initModels(path + "/assets/mModelEncoder.ort", path + "/assets/mModelDecoder.ort", path + "/assets/mLogSoftMax.ort", acc);
+#else
+ initModels(path + "/assets/mModelEncoder.onnx", path + "/assets/mModelDecoder.onnx", path + "/assets/mLogSoftMax.onnx", acc);
+#endif
+}
+
+ModelProcessor::~ModelProcessor()
+{
+ endModels();
+ Plog::log(Plog::LogPriority::INFO, TAG, "~ModelProcessor");
+}
+
+void
+ModelProcessor::endModels()
+{
+ if (encoderSession_) {
+ delete encoderSession_;
+ encoderSession_ = nullptr;
+ }
+ if (decoderSession_) {
+ delete decoderSession_;
+ decoderSession_ = nullptr;
+ }
+ if (logSoftMaxSession_) {
+ delete logSoftMaxSession_;
+ logSoftMaxSession_ = nullptr;
+ }
+ if (env_)
+ env_.release();
+ env_ = NULL;
+}
+
+void
+ModelProcessor::initModels(const std::string& encoderModelPath, const std::string& decoderModelPath, const std::string& logSoftMaxModelPath, bool activateAcc)
+{
+ try {
+ sessOpt_ = Ort::SessionOptions();
+
+#ifdef NVIDIA
+ if (activateAcc)
+ Ort::ThrowOnError(OrtSessionOptionsAppendExecutionProvider_CUDA(sessOpt_, 0));
+#endif
+#ifdef __ANDROID__
+ if (activateAcc)
+ Ort::ThrowOnError(OrtSessionOptionsAppendExecutionProvider_Nnapi(sessOpt_, 0));
+#endif
+
+ sessOpt_.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_ALL);
+#ifdef WIN32
+ encoderSession_ = new Ort::Session(env_, string_utils::to_wstring(encoderModelPath).c_str(), sessOpt_);
+ decoderSession_ = new Ort::Session(env_, string_utils::to_wstring(decoderModelPath).c_str(), sessOpt_);
+ logSoftMaxSession_ = new Ort::Session(env_, string_utils::to_wstring(logSoftMaxModelPath).c_str(), sessOpt_);
+#else
+ encoderSession_ = new Ort::Session(env_, encoderModelPath.c_str(), sessOpt_);
+ decoderSession_ = new Ort::Session(env_, decoderModelPath.c_str(), sessOpt_);
+ logSoftMaxSession_ = new Ort::Session(env_, logSoftMaxModelPath.c_str(), sessOpt_);
+#endif
+ isAllocated_ = true;
+ Plog::log(Plog::LogPriority::INFO, TAG, "Model is allocated");
+ } catch (std::exception& e) {
+ Plog::log(Plog::LogPriority::ERR, TAG, e.what());
+ }
+}
+
+/* from whisper.cpp */
+// the most basic sampling scheme - select the top token
+whisperTokenData
+ModelProcessor::whisper_sample_best(const float * probs)
+{
+ whisperTokenData result = {
+ 0, 0, 0.0f, 0.0f, 0.0f, -1, -1, 0.0f,
+ };
+
+ int n_logits = vocab_.id_to_token.size();
+
+ std::vector<std::pair<double, int64_t>> probs_id;
+ probs_id.reserve(n_logits);
+
+ for (int i = 0; i < n_logits; i++) {
+ probs_id.push_back(std::make_pair(probs[i], i));
+ }
+
+ {
+ double sum_ts = 0.0;
+ double max_ts = -1.0;
+ double max_tx = -1.0;
+
+ for (int i = 0; i < vocab_.token_beg; i++) {
+ max_tx = std::max(max_tx, probs_id[i].first);
+ }
+
+ for (int i = vocab_.token_beg; i < n_logits; i++) {
+ sum_ts += probs_id[i].first;
+ if (probs_id[i].first > max_ts) {
+ max_ts = probs_id[i].first;
+ result.tid = probs_id[i].second;
+ }
+ }
+
+ // if the probability sum of all timestamp tokens is higher than the max probability of the text tokens - sample a
+ // timestamp token
+ if (sum_ts > max_tx) {
+ // ref: https://github.com/openai/whisper/blob/0b1ba3d46ebf7fe6f953acfd8cad62a4f851b49f/whisper/decoding.py#L430-L438
+ for (int i = 0; i < vocab_.token_beg; i++) {
+ probs_id[i].first = -__INT_MAX__;
+ }
+ }
+
+ result.pt = max_ts/(sum_ts + 1e-10);
+ result.ptsum = sum_ts;
+ }
+
+ // find the top K tokens
+ const int top_k = 4;
+
+ std::partial_sort(
+ probs_id.begin(),
+ probs_id.begin() + top_k, probs_id.end(),
+ [](const std::pair<double, int64_t> & a, const std::pair<double, int64_t> & b) {
+ return a.first > b.first;
+ });
+
+ probs_id.resize(top_k);
+
+ int res = 0;
+ while ((probs_id[res].second == vocab_.token_sot ||
+ probs_id[res].second == vocab_.token_solm ||
+ probs_id[res].second == vocab_.token_beg) &&
+ res < (int) probs_id.size() - 1) {
+ res++;
+ }
+
+ result.id = probs_id[res].second;
+ result.p = probs_id[res].first;
+
+ return result;
+}
+
+whisperTokenData
+ModelProcessor::getToken(std::vector<float>& logits)
+{
+ std::vector<Ort::Value> logSoftMaxInputs;
+ logSoftMaxInputs.push_back(Ort::Value::CreateTensor<float>(allocatorInfo_,
+ logits.data(),
+ logits.size(),
+ logitsShape_.data(),
+ logitsShape_.size()));
+
+ auto softmaxOutputs = logSoftMaxSession_->Run(Ort::RunOptions {nullptr},
+ logSoftMaxInputNames.data(),
+ logSoftMaxInputs.data(),
+ logSoftMaxInputNames.size(),
+ logSoftMaxOutputNames.data(),
+ logSoftMaxOutputNames.size());
+
+ float* probs = softmaxOutputs[1].GetTensorMutableData<float>();
+ return whisper_sample_best(probs);
+}
+
+std::string
+ModelProcessor::getText()
+{
+ std::ostringstream oss;
+ for (auto token : tokensOutput_) {
+ if (token < vocab_.token_eot)
+ oss << vocab_.id_to_token[token];
+ }
+
+ tokensOutput_.clear();
+ return oss.str();
+}
+
+void
+ModelProcessor::feedInput(std::vector<float>& melInput)
+{
+ try {
+ Ort::Value melInputTensor = Ort::Value::CreateTensor<float>(allocatorInfo_,
+ melInput.data(),
+ melInput.size(),
+ melInputShape_.data(),
+ melInputShape_.size());
+ audioFeaturesTensor_ = Ort::Value::CreateTensor<float>(allocatorInfo_,
+ audioFeatures_.data(),
+ audioFeatures_.size(),
+ audioFeaturesShape_.data(),
+ audioFeaturesShape_.size());
+ // Run the encoder graph
+ encoderSession_->Run(Ort::RunOptions {nullptr},
+ encoderInputNames,
+ &melInputTensor,
+ 1,
+ encoderOutputNames,
+ &audioFeaturesTensor_,
+ 1);
+ } catch(Ort::Exception e) {
+ Plog::log(Plog::LogPriority::ERR, TAG, e.what());
+ return;
+ } catch (...) {
+ return;
+ }
+
+ try {
+ std::vector<int64_t> currentTokens;
+ currentTokens.emplace_back(vocab_.token_sot);
+ std::vector<float> currentKVCache(12 * 1 * 1 * 512, 0.0f);
+ std::array<int64_t, 1> offsetShape {1};
+ std::array<int64_t, 2> tokenShape {1, 1};
+
+ for (auto i = 0; i < sampleLen; i++) {
+ int64_t offset = i;
+ std::array<int64_t, 4> kvCacheShape { 12, 1, (i + 1), 512 };
+
+ std::vector<int64_t> token = { currentTokens.back() };
+
+ // Run the decoder graph
+ std::vector<Ort::Value> inputsVector; // {audioFeaturesTensor_, tokensTensor_, kvCacheTensor_, offsetTensor_};
+ inputsVector.push_back(Ort::Value::CreateTensor<float>(allocatorInfo_,
+ audioFeatures_.data(),
+ audioFeatures_.size(),
+ audioFeaturesShape_.data(),
+ audioFeaturesShape_.size()));
+
+ inputsVector.emplace_back(Ort::Value::CreateTensor<int64_t>(allocatorInfo_,
+ token.data(),
+ token.size(),
+ tokenShape.data(),
+ tokenShape.size()));
+
+ inputsVector.emplace_back(Ort::Value::CreateTensor<float>(allocatorInfo_,
+ currentKVCache.data(),
+ currentKVCache.size(),
+ kvCacheShape.data(),
+ kvCacheShape.size()));
+
+ inputsVector.emplace_back(Ort::Value::CreateTensor<int64_t>(allocatorInfo_,
+ &offset,
+ 1,
+ offsetShape.data(),
+ 0));
+
+ auto outputs = decoderSession_->Run(Ort::RunOptions {nullptr},
+ decoderInputNames.data(),
+ inputsVector.data(),
+ decoderInputNames.size(),
+ decoderOutputNames.data(),
+ decoderOutputNames.size());
+
+ auto logitsTensorInfo = outputs[0].GetTensorTypeAndShapeInfo();
+ auto logitsData = outputs[0].GetTensorMutableData<float>();
+
+ {
+ std::vector<float>logits(logitsData, logitsData + logitsTensorInfo.GetElementCount());
+ auto tokenData = getToken(logits);
+ currentTokens.push_back(tokenData.id);
+ }
+
+ // Grab kvCache for next iteration
+ auto kvCacheTensorInfo = outputs[1].GetTensorTypeAndShapeInfo();
+ auto nextKVCacheData = outputs[1].GetTensorMutableData<float>();
+
+ std::vector<float> nextKVCache;
+ std::vector<float> zeros(512, 0.0f);
+ int delta = (i + 1) * 512;
+ for (int currentKVIdx = 0; currentKVIdx < 12; currentKVIdx++) {
+ nextKVCache.insert(nextKVCache.end(),
+ nextKVCacheData + (currentKVIdx * delta),
+ nextKVCacheData + ((currentKVIdx + 1) * delta));
+ nextKVCache.insert(nextKVCache.end(), zeros.begin(), zeros.end());
+ }
+ std::swap(currentKVCache, nextKVCache);
+
+ if (currentTokens.back() == vocab_.token_eot)
+ break;
+ }
+
+ std::swap(currentTokens, tokensOutput_);
+ } catch(Ort::Exception e) {
+ Plog::log(Plog::LogPriority::ERR, TAG, e.what());
+ return;
+ } catch (...) {
+ return;
+ }
+
+ modelInit_ = false;
+}
+} // namespace jami
diff --git a/WhisperTranscript/ModelProcessor.h b/WhisperTranscript/ModelProcessor.h
new file mode 100644
index 0000000..4a2ad17
--- /dev/null
+++ b/WhisperTranscript/ModelProcessor.h
@@ -0,0 +1,120 @@
+/**
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#pragma once
+
+#include <map>
+#include <vector>
+#include <algorithm>
+
+#include <onnxruntime_cxx_api.h>
+#ifdef __ANDROID__
+#include <nnapi_provider_factory.h>
+#endif
+
+#include <functional>
+
+#include "Preprocess.h"
+
+namespace jami {
+
+static const char* encoderInputNames[4] = {"mel"};
+static const char* encoderOutputNames[4] = {"903"};
+
+static const std::vector<const char*> decoderInputNames = {"audio_features", "tokens", "kv_cache", "offset"};
+static const std::vector<const char*> decoderOutputNames = {"logits", "output_kv_cache"};
+
+static const std::vector<const char *> logSoftMaxInputNames = {"logits"};
+static const std::vector<const char *> logSoftMaxOutputNames = {"token_ids", "probs"};
+
+typedef struct whisperTokenData {
+ int64_t id; // token id
+ int64_t tid; // forced timestamp token id
+
+ float p; // probability of the token
+ float pt; // probability of the timestamp token
+ float ptsum; // sum of probabilities of all timestamp tokens
+
+ // token-level timestamp data
+ // do not use if you haven't computed token-level timestamps
+ int64_t t0; // start time of the token
+ int64_t t1; // end time of the token
+
+ float vlen; // voice length of the token
+} whisperTokenData;
+
+class ModelProcessor
+{
+public:
+ ModelProcessor(const std::string& path, bool acc);
+ ~ModelProcessor();
+
+ void initModels(const std::string& encoderModelPath, const std::string& decoderModelPath, const std::string& logSoftMaxModelPath, bool activateAcc);
+ void endModels();
+
+ whisperTokenData whisper_sample_best(const float * probs);
+
+ /**
+ * @brief feedInput
+ * Takes a frame and feeds it to the model storage for predictions
+ * @param frame
+ */
+ void feedInput(std::vector<float>& input);
+
+ bool isAllocated() { return isAllocated_; }
+
+ std::string getText();
+
+private:
+ bool modelInit_ = true;
+
+ // Tokens
+ whisperVocab vocab_;
+
+ whisperTokenData getToken(std::vector<float>& logits);
+
+ // onnx related
+ Ort::MemoryInfo allocatorInfo_ = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
+ bool isAllocated_ {false};
+ Ort::Env env_ {ORT_LOGGING_LEVEL_WARNING, "whisperTest"};
+ Ort::Session* encoderSession_ {};
+ Ort::Session* decoderSession_ {};
+ Ort::Session* logSoftMaxSession_ {};
+ Ort::SessionOptions sessOpt_;
+
+ // Encoder tensors. 1 input and 1 output
+ std::vector<int64_t> melInputShape_ {1, 80, 3000}; // Input Data Type: 1 (float), Input Shape: [1, 80, 3000]
+ Ort::Value audioFeaturesTensor_ {nullptr};
+ std::vector<int64_t> audioFeaturesShape_ {1, 1500, 512}; // Output Data Type: 1 (float), Output Shape: [1, 1500, 512]
+ std::array<float, 1500 * 512> audioFeatures_ {};
+
+ std::vector<float> output_;
+
+ // Decoder tensors. 4 inputs and 2 outputs
+ std::vector<int64_t> tokensOutput_ { };
+
+ // LogProb check
+ std::array<int64_t, 3> logitsShape_ {1, 1, 51864};
+
+ int sampleLen = 50;
+
+};
+} // namespace jami
diff --git a/WhisperTranscript/PluginPreferenceHandler.cpp b/WhisperTranscript/PluginPreferenceHandler.cpp
new file mode 100644
index 0000000..202f70d
--- /dev/null
+++ b/WhisperTranscript/PluginPreferenceHandler.cpp
@@ -0,0 +1,109 @@
+/**
+ * Copyright (C) 2021 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "PluginPreferenceHandler.h"
+
+#include "TranscriptMediaHandler.h"
+#include "pluglog.h"
+
+const char sep = separator();
+const std::string TAG = "TranscriptAcc";
+
+#define NAME "TranscriptAcc"
+
+namespace jami {
+
+PluginPreferenceHandler::PluginPreferenceHandler(
+ const JAMI_PluginAPI* api,
+ std::map<std::string, std::map<std::string, std::string>>&& preferences,
+ const std::string& dataPath)
+ : api_ {api}
+ , datapath_ {dataPath}
+{
+ preferences_ = preferences;
+ setId(datapath_);
+};
+
+std::map<std::string, std::string>
+PluginPreferenceHandler::getHandlerDetails()
+{
+ return {{"name", NAME}, {"iconPath", datapath_ + sep + "icon.svg"}, {"pluginId", id()}};
+}
+
+void
+PluginPreferenceHandler::setPreferenceAttribute(const std::string& accountId,
+ const std::string& key,
+ const std::string& value)
+{
+ if (accountId.empty()) {
+ for (auto& prefMap : preferences_) {
+ auto it = prefMap.second.find(key);
+ if (it != prefMap.second.end() && it->second != value) {
+ it->second = value;
+ }
+ }
+ } else {
+ auto accIt = preferences_.find("default");
+ accIt = preferences_.emplace(accountId, preferences_["default"]).first;
+ auto it = accIt->second.find(key);
+ if (it != accIt->second.end() && it->second != value) {
+ it->second = value;
+ }
+ }
+
+ tmh_->setParameters(accountId);
+}
+
+void
+PluginPreferenceHandler::resetPreferenceAttributes(const std::string& accountId)
+{
+ std::lock_guard<std::mutex> lk(mtx_);
+ if (accountId.empty()) {
+ preferences_.clear();
+ api_->invokeService(api_, "getPluginAccPreferences", &preferences_);
+ } else
+ preferences_[accountId] = preferences_["default"];
+ tmh_->setParameters(accountId);
+}
+
+bool
+PluginPreferenceHandler::preferenceMapHasKey(const std::string& key)
+{
+ return (key == "background" || key == "position" || key == "fontsize");
+}
+
+std::map<std::string, std::string>
+PluginPreferenceHandler::getPreferences(const std::string& accountId)
+{
+ std::lock_guard<std::mutex> lk(mtx_);
+ return preferences_.emplace(accountId, preferences_["default"]).first->second;
+}
+
+PluginPreferenceHandler::~PluginPreferenceHandler()
+{
+ preferences_.clear();
+}
+
+void
+PluginPreferenceHandler::setTranscriptHandler(TranscriptMediaHandler* handler)
+{
+ tmh_ = handler;
+}
+} // namespace jami
diff --git a/WhisperTranscript/PluginPreferenceHandler.h b/WhisperTranscript/PluginPreferenceHandler.h
new file mode 100644
index 0000000..a45e12b
--- /dev/null
+++ b/WhisperTranscript/PluginPreferenceHandler.h
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 2021 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include "plugin/jamiplugin.h"
+#include "plugin/preferencehandler.h"
+
+#include <string>
+#include <map>
+#include <memory>
+#include <set>
+#include <mutex>
+
+namespace jami {
+class TranscriptMediaHandler;
+
+class PluginPreferenceHandler : public jami::PreferenceHandler
+{
+public:
+ PluginPreferenceHandler(const JAMI_PluginAPI* api,
+ std::map<std::string, std::map<std::string, std::string>>&& preferences,
+ const std::string& dataPath);
+ ~PluginPreferenceHandler();
+
+ std::map<std::string, std::string> getHandlerDetails() override;
+ bool preferenceMapHasKey(const std::string& key) override;
+ void setPreferenceAttribute(const std::string& accountId,
+ const std::string& key,
+ const std::string& value) override;
+ void resetPreferenceAttributes(const std::string& accountId) override;
+
+ std::map<std::string, std::string> getPreferences(const std::string& accountId);
+ void setTranscriptHandler(TranscriptMediaHandler* handler);
+
+private:
+ const JAMI_PluginAPI* api_;
+ TranscriptMediaHandler* tmh_;
+ const std::string datapath_;
+ std::map<std::string, std::map<std::string, std::string>> preferences_;
+ std::mutex mtx_;
+};
+} // namespace jami
diff --git a/WhisperTranscript/Preprocess.cpp b/WhisperTranscript/Preprocess.cpp
new file mode 100644
index 0000000..706c44f
--- /dev/null
+++ b/WhisperTranscript/Preprocess.cpp
@@ -0,0 +1,310 @@
+/**
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "Preprocess.h"
+
+#ifdef WIN32
+#define _USE_MATH_DEFINES
+#endif
+
+#include <thread>
+#include <math.h>
+#include <fstream>
+#include <iostream>
+
+// ref: https://github.com/openai/whisper/blob/main/whisper/audio.py#L92-L124
+bool logMelSpectrogram(
+ const float *samples,
+ const int n_samples,
+ const int n_threads,
+ const whisperFilters &filters,
+ whisperMel &mel) {
+
+ // const int sample_rate = WHISPER_SAMPLE_RATE;
+ const int fft_size = WHISPER_N_FFT;
+ const int fft_step = WHISPER_HOP_LENGTH;
+ const int n_mel = WHISPER_N_MEL;
+
+ // Hanning window
+ std::vector<float> hann;
+ hann.resize(fft_size);
+ for (int i = 0; i < fft_size; i++) {
+ hann[i] = 0.5*(1.0 - cos((2.0*M_PI*i)/(fft_size)));
+ }
+
+ mel.n_mel = n_mel;
+ mel.n_len = (n_samples)/fft_step;
+ mel.data.resize(mel.n_mel*mel.n_len);
+
+ const int n_fft = 1 + fft_size/2;
+
+ std::vector<std::thread> workers(n_threads);
+ for (int iw = 0; iw < n_threads; ++iw) {
+ workers[iw] = std::thread([&](int ith) {
+ std::vector<float> fft_in;
+ fft_in.resize(fft_size);
+ for (int i = 0; i < fft_size; i++) {
+ fft_in[i] = 0.0;
+ }
+
+ std::vector<float> fft_out;
+ fft_out.resize(2*fft_size);
+
+ for (int i = ith; i < mel.n_len; i += n_threads) {
+ const int offset = i*fft_step;
+
+ // apply Hanning window
+ for (int j = 0; j < fft_size; j++) {
+ if (offset + j < n_samples) {
+ fft_in[j] = hann[j]*samples[offset + j];
+ } else {
+ fft_in[j] = 0.0;
+ }
+ }
+
+ // FFT -> mag^2
+ fft(fft_in, fft_out);
+
+ for (int j = 0; j < fft_size; j++) {
+ fft_out[j] = (fft_out[2*j + 0]*fft_out[2*j + 0] + fft_out[2*j + 1]*fft_out[2*j + 1]);
+ }
+ for (int j = 1; j < fft_size/2; j++) {
+ fft_out[j] += fft_out[fft_size - j];
+ }
+
+ // mel spectrogram
+ for (int j = 0; j < mel.n_mel; j++) {
+ double sum = 0.0;
+
+ for (int k = 0; k < n_fft; k++) {
+ sum += fft_out[k]*filters.data[j*n_fft + k];
+ }
+ if (sum < 1e-10) {
+ sum = 1e-10;
+ }
+
+ sum = log10(sum);
+
+ mel.data[j*mel.n_len + i] = sum;
+ }
+ }
+ }, iw);
+ }
+
+ for (int iw = 0; iw < n_threads; ++iw) {
+ workers[iw].join();
+ }
+
+ // clamping and normalization
+ double mmax = -1e20;
+ for (int i = 0; i < mel.n_mel*mel.n_len; i++) {
+ if (mel.data[i] > mmax) {
+ mmax = mel.data[i];
+ }
+ }
+
+ mmax -= 8.0;
+
+ for (int i = 0; i < mel.n_mel*mel.n_len; i++) {
+ if (mel.data[i] < mmax) {
+ mel.data[i] = mmax;
+ }
+
+ mel.data[i] = (mel.data[i] + 4.0)/4.0;
+ }
+
+ return true;
+}
+
+// Cooley-Tukey FFT
+// poor man's implementation - use something better
+// input is real-valued
+// output is complex-valued
+void fft(const std::vector<float> & in, std::vector<float> & out) {
+ out.resize(in.size()*2);
+
+ int N = in.size();
+
+ if (N == 1) {
+ out[0] = in[0];
+ out[1] = 0;
+ return;
+ }
+
+ if (N%2 == 1) {
+ dft(in, out);
+ return;
+ }
+
+ std::vector<float> even;
+ std::vector<float> odd;
+
+ for (int i = 0; i < N; i++) {
+ if (i % 2 == 0) {
+ even.push_back(in[i]);
+ } else {
+ odd.push_back(in[i]);
+ }
+ }
+
+ std::vector<float> even_fft;
+ std::vector<float> odd_fft;
+
+ fft(even, even_fft);
+ fft(odd, odd_fft);
+
+ for (int k = 0; k < N/2; k++) {
+ float theta = 2*M_PI*k/N;
+
+ float re = cos(theta);
+ float im = -sin(theta);
+
+ float re_odd = odd_fft[2*k + 0];
+ float im_odd = odd_fft[2*k + 1];
+
+ out[2*k + 0] = even_fft[2*k + 0] + re*re_odd - im*im_odd;
+ out[2*k + 1] = even_fft[2*k + 1] + re*im_odd + im*re_odd;
+
+ out[2*(k + N/2) + 0] = even_fft[2*k + 0] - re*re_odd + im*im_odd;
+ out[2*(k + N/2) + 1] = even_fft[2*k + 1] - re*im_odd - im*re_odd;
+ }
+}
+
+// naive Discrete Fourier Transform
+// input is real-valued
+// output is complex-valued
+void dft(const std::vector<float> & in, std::vector<float> & out) {
+ int N = in.size();
+
+ out.resize(N*2);
+
+ for (int k = 0; k < N; k++) {
+ float re = 0;
+ float im = 0;
+
+ for (int n = 0; n < N; n++) {
+ float angle = 2*M_PI*k*n/N;
+ re += in[n]*cos(angle);
+ im -= in[n]*sin(angle);
+ }
+
+ out[k*2 + 0] = re;
+ out[k*2 + 1] = im;
+ }
+}
+
+
+void loadMelFilters(const std::string& fileName, whisperFilters& filters) {
+ auto fin = std::ifstream(fileName, std::ios::binary);
+ if (!fin) {
+ fprintf(stderr, "%s: failed to open '%s'\n", __func__, fileName.c_str());
+ return;
+ }
+
+ fin.read((char *) &filters.n_mel, sizeof(filters.n_mel));
+ fin.read((char *) &filters.n_fft, sizeof(filters.n_fft));
+
+ filters.data.resize(filters.n_mel * filters.n_fft);
+ fin.read((char *) filters.data.data(), filters.data.size() * sizeof(float));
+}
+
+void loadTokens(const std::string& fileName, whisperVocab& vocab) {
+ auto fin = std::ifstream(fileName, std::ios::binary);
+ if (!fin) {
+ fprintf(stderr, "%s: failed to open '%s'\n", __func__, fileName.c_str());
+ return;
+ }
+
+ int32_t modelNVocab = 0;
+ fin.read((char *) &modelNVocab, sizeof(modelNVocab));
+
+ int32_t tokensNVocab = 0;
+ fin.read((char *) &tokensNVocab, sizeof(tokensNVocab));
+
+ std::string word;
+ for (int i = 0; i < tokensNVocab; i++) {
+ uint32_t len;
+ fin.read((char *) &len, sizeof(len));
+
+ word.resize(len);
+ fin.read((char *) word.data(), len);
+
+ vocab.token_to_id[word] = i;
+ vocab.id_to_token[i] = word;
+ }
+
+ vocab.n_vocab = modelNVocab;
+ if (vocab.is_multilingual()) {
+ vocab.token_eot++;
+ vocab.token_sot++;
+ vocab.token_prev++;
+ vocab.token_solm++;
+ vocab.token_not++;
+ vocab.token_beg++;
+ }
+
+ if (tokensNVocab < modelNVocab) {
+ fprintf(stderr, "%s: adding %d extra tokens\n", __func__, modelNVocab - tokensNVocab);
+ for (int i = tokensNVocab; i < modelNVocab; i++) {
+ if (i > vocab.token_beg) {
+ word = "[_TT_" + std::to_string(i - vocab.token_beg) + "]";
+ } else if (i == vocab.token_eot) {
+ word = "[_EOT_]";
+ } else if (i == vocab.token_sot) {
+ word = "[_SOT_]";
+ } else if (i == vocab.token_prev) {
+ word = "[_PREV_]";
+ } else if (i == vocab.token_not) {
+ word = "[_NOT_]";
+ } else if (i == vocab.token_beg) {
+ word = "[_BEG_]";
+ } else {
+ word = "[_extra_token_" + std::to_string(i) + "]";
+ }
+ vocab.token_to_id[word] = i;
+ vocab.id_to_token[i] = word;
+ }
+ }
+}
+
+void
+inputPadTrim(whisperMel &mel)
+{
+ if (mel.n_len == ENCODER_INPUT_LEN)
+ return;
+ std::vector<float> data;
+ std::vector<float> partialData;
+ int seek = 0;
+ auto dataLimit = std::min(mel.n_len, ENCODER_INPUT_LEN);
+ for (auto j = 0; j < mel.n_mel; j++) {
+ seek = j * mel.n_len;
+ for (auto i = seek; i < (j + 1) * dataLimit; i++) {
+ partialData.emplace_back(mel.data[i]);
+ }
+ if (mel.n_len < ENCODER_INPUT_LEN) {
+ for (auto i = mel.n_len; i < ENCODER_INPUT_LEN; i++) {
+ partialData.emplace_back(0.0f);
+ }
+ }
+ data.insert(data.end(), partialData.begin(), partialData.end());
+ partialData.clear();
+ }
+ std::swap(mel.data, data);
+}
diff --git a/WhisperTranscript/Preprocess.h b/WhisperTranscript/Preprocess.h
new file mode 100644
index 0000000..455a96e
--- /dev/null
+++ b/WhisperTranscript/Preprocess.h
@@ -0,0 +1,91 @@
+/**
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <vector>
+#include <cstdint>
+#include <string>
+#include <map>
+
+
+// Those are model defined
+// Check paper page 3 (https://cdn.openai.com/papers/whisper.pdf)
+#define WHISPER_SAMPLE_RATE 16000
+#define WHISPER_N_FFT 400
+#define WHISPER_N_MEL 80
+#define WHISPER_HOP_LENGTH 160
+#define WHISPER_CHUNK_SIZE 30
+#define ENCODER_INPUT_LEN 3000
+
+struct whisperMel {
+ int n_len;
+ int n_mel;
+
+ std::vector<float> data;
+};
+
+struct whisperFilters {
+ int32_t n_mel;
+ int32_t n_fft;
+
+ std::vector<float> data;
+};
+
+struct whisperVocab {
+ int n_vocab = 51864;
+
+ std::map<std::string, int32_t> token_to_id;
+ std::map<int32_t, std::string> id_to_token;
+
+ int32_t token_eot = 50256;
+ int32_t token_sot = 50257;
+ int32_t token_prev = 50360;
+ int32_t token_solm = 50361; // no speech
+ int32_t token_not = 50362; // no timestamps
+ int32_t token_beg = 50363; // timestamp begin
+
+ // available tasks
+ static const int32_t token_translate = 50358;
+ static const int32_t token_transcribe = 50359;
+
+ bool is_multilingual() const {
+ return n_vocab == 51865;
+ }
+
+ std::vector<std::vector<int>> filters;
+};
+
+bool logMelSpectrogram(
+ const float * samples,
+ const int n_samples,
+ const int n_threads,
+ const whisperFilters & filters,
+ whisperMel &mel);
+
+void fft(const std::vector<float> & in, std::vector<float> & out);
+
+void dft(const std::vector<float> & in, std::vector<float> & out);
+
+void loadMelFilters(const std::string& fileName, whisperFilters& filters);
+
+void loadTokens(const std::string& fileName, whisperVocab& vocab);
+
+void inputPadTrim(whisperMel &mel);
diff --git a/WhisperTranscript/TranscriptAudioSubscriber.cpp b/WhisperTranscript/TranscriptAudioSubscriber.cpp
new file mode 100644
index 0000000..d341671
--- /dev/null
+++ b/WhisperTranscript/TranscriptAudioSubscriber.cpp
@@ -0,0 +1,168 @@
+/**
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "TranscriptAudioSubscriber.h"
+
+#include <pluglog.h>
+#include <frameUtils.h>
+#include <bitset>
+#include <iostream>
+
+const std::string TAG = "Transcript";
+const char sep = separator();
+
+namespace jami {
+
+TranscriptAudioSubscriber::TranscriptAudioSubscriber(const std::string& dataPath, TranscriptVideoSubscriber* videoSubscriber, bool acc)
+ : path_ {dataPath}
+ , modelProcessor_ {dataPath, acc}
+ , mVS_ {videoSubscriber}
+{
+ loadMelFilters(path_ + "/assets/mel_filters.bin", modelFilters_);
+
+ /**
+ * Waits for audio samples and then process them
+ **/
+ processFrameThread = std::thread([this] {
+ while (running) {
+ std::unique_lock<std::mutex> l(inputLock);
+ inputCv.wait(l, [this] { return not running or newFrame; });
+ if (not running) {
+ break;
+ }
+
+ logMelSpectrogram(currentModelInput_.data(), currentModelInput_.size(), 8, modelFilters_, melSpectrogram_);
+ inputPadTrim(melSpectrogram_);
+ newFrame = false;
+
+ currentModelInput_.clear();
+#ifndef __DEBUG__
+ /** Unlock the mutex, this way we let the other thread
+ * copy new data while we are processing the old one
+ **/
+ l.unlock();
+#endif
+ modelProcessor_.feedInput(melSpectrogram_.data);
+ auto text = modelProcessor_.getText();
+ mVS_->setText(text);
+ }
+ });
+}
+
+TranscriptAudioSubscriber::~TranscriptAudioSubscriber()
+{
+ modelProcessor_.endModels();
+ formatFilter_.clean();
+ stop();
+ processFrameThread.join();
+ Plog::log(Plog::LogPriority::INFO, TAG, "~TranscriptMediaProcessor");
+}
+
+void
+TranscriptAudioSubscriber::stop()
+{
+ running = false;
+ inputCv.notify_all();
+}
+
+void
+TranscriptAudioSubscriber::update(jami::Observable<AVFrame*>*, AVFrame* const& pluginFrame)
+{
+ if (!pluginFrame || modelFilters_.data.empty())
+ return;
+
+ if (firstRun) {
+ modelProcessor_.getText();
+ count_ = 0;
+ pastModelInput_.clear();
+ currentModelInput_.clear();
+ futureModelInput_.clear();
+ formatFilter_.clean();
+ AudioFormat afmt = AudioFormat(pluginFrame->sample_rate,
+ pluginFrame->channels,
+ static_cast<AVSampleFormat>(pluginFrame->format));
+ MediaStream ms = MediaStream("input", afmt);
+ formatFilter_.initialize(filterDescription_, {ms});
+ firstRun = false;
+ }
+
+ if (!formatFilter_.initialized_)
+ return;
+
+ if (formatFilter_.feedInput(pluginFrame, "input") == 0) {
+ uniqueFramePtr filteredFrame = {formatFilter_.readOutput(), frameFree};
+ if (filteredFrame) {
+ for (size_t i = 0; i < filteredFrame->buf[0]->size; i += 2) {
+ std::lock_guard<std::mutex> l(inputLock);
+ int16_t rawValue = (filteredFrame->buf[0]->data[i+1] << 8) | filteredFrame->buf[0]->data[i];
+
+ // If not a positive value, perform the 2's complement math on the value
+ if ((rawValue & 0x8000) != 0) {
+ rawValue = (~(rawValue - 0x0001)) * -1;
+ }
+ futureModelInput_.emplace_back(float(rawValue)/32768.0f);
+ if (count_++ > WHISPER_STREAM_SAMPLES_CHUNK_STEP)
+ overlapInput_.emplace_back(float(rawValue)/32768.0f);
+ count_++;
+
+ // Trigger transcription when we have enough samples
+ if (futureModelInput_.size() == WHISPER_STREAM_SAMPLES_CHUNK && !newFrame) {
+ pastModelInput_.clear();
+ std::swap(pastModelInput_, currentModelInput_);
+ std::swap(currentModelInput_, futureModelInput_);
+ std::swap(futureModelInput_, overlapInput_);
+ count_ = 0;
+ overlapInput_.clear();
+ newFrame = true;
+ inputCv.notify_all();
+ }
+ }
+ }
+ }
+ // audio returns as is
+}
+
+void
+TranscriptAudioSubscriber::attached(jami::Observable<AVFrame*>* observable)
+{
+ Plog::log(Plog::LogPriority::INFO, TAG, "::Attached ! ");
+ observable_ = observable;
+}
+
+void
+TranscriptAudioSubscriber::detached(jami::Observable<AVFrame*>*)
+{
+ modelProcessor_.getText();
+ firstRun = true;
+ observable_ = nullptr;
+ Plog::log(Plog::LogPriority::INFO, TAG, "::Detached()");
+}
+
+void
+TranscriptAudioSubscriber::detach()
+{
+ if (observable_) {
+ firstRun = true;
+ std::ostringstream oss;
+ Plog::log(Plog::LogPriority::INFO, TAG, "::Calling detach()");
+ observable_->detach(this);
+ }
+}
+} // namespace jami
diff --git a/WhisperTranscript/TranscriptAudioSubscriber.h b/WhisperTranscript/TranscriptAudioSubscriber.h
new file mode 100644
index 0000000..b9b717e
--- /dev/null
+++ b/WhisperTranscript/TranscriptAudioSubscriber.h
@@ -0,0 +1,93 @@
+/**
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+extern "C" {
+#include <libavutil/frame.h>
+}
+#include <observer.h>
+
+#include <frameFilter.h>
+
+#include "Preprocess.h"
+#include "ModelProcessor.h"
+#include "TranscriptVideoSubscriber.h"
+
+#include <thread>
+#include <condition_variable>
+
+namespace jami {
+
+#define WHISPER_STREAM_SAMPLES_CHUNK 16000 * 4 // 16 KHz * 4 seconds
+#define WHISPER_STREAM_SAMPLES_CHUNK_STEP 16000 * 3 // 16KHz * 3 second
+
+class TranscriptAudioSubscriber : public Observer<AVFrame*>
+{
+public:
+ TranscriptAudioSubscriber(const std::string& dataPath, TranscriptVideoSubscriber* videoSubscriber, bool acc = false);
+ ~TranscriptAudioSubscriber();
+
+ virtual void update(Observable<AVFrame*>*, AVFrame* const&) override;
+ virtual void attached(Observable<AVFrame*>*) override;
+ virtual void detached(Observable<AVFrame*>*) override;
+
+ void detach();
+
+private:
+ // Mel spectrogram filters
+ whisperFilters modelFilters_;
+ whisperMel melSpectrogram_;
+
+ // Observer pattern
+ Observable<AVFrame*>* observable_{};
+
+ // Filter for audio formatting
+ const std::string filterDescription_ = "[input]aresample=16000,aformat=sample_fmts=s16:channel_layouts=mono";
+ FrameFilter formatFilter_;
+ std::vector<float> currentModelInput_{};
+ std::vector<float> futureModelInput_{};
+ std::vector<float> pastModelInput_{};
+ std::vector<float> overlapInput_{};
+
+ // Data
+ std::string path_;
+
+ // Status variables of the processing
+ bool firstRun {true};
+ bool running {true};
+ bool newFrame {false};
+
+ // Stream count
+ int count_;
+
+ // Model
+ ModelProcessor modelProcessor_;
+
+ // Threading
+ std::thread processFrameThread;
+ std::mutex inputLock;
+ std::condition_variable inputCv;
+ void stop();
+
+ // Video processor
+ TranscriptVideoSubscriber* mVS_{};
+};
+} // namespace jami
diff --git a/WhisperTranscript/TranscriptMediaHandler.cpp b/WhisperTranscript/TranscriptMediaHandler.cpp
new file mode 100644
index 0000000..3e30733
--- /dev/null
+++ b/WhisperTranscript/TranscriptMediaHandler.cpp
@@ -0,0 +1,133 @@
+/**
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "TranscriptMediaHandler.h"
+
+#include "pluglog.h"
+#include <string_view>
+
+const char sep = separator();
+const std::string TAG = "Transcript";
+
+#define NAME "Transcript"
+
+namespace jami {
+
+TranscriptMediaHandler::TranscriptMediaHandler(std::string&& datapath, PluginPreferenceHandler* prefHandler)
+ : datapath_ {datapath}
+{
+ aph_ = prefHandler;
+ setId(datapath_);
+ videoSubscriber_ = std::make_shared<TranscriptVideoSubscriber>(datapath_);
+ audioSubscriber_ = std::make_shared<TranscriptAudioSubscriber>(datapath_, videoSubscriber_.get());
+ setParameters("default");
+#ifdef __DEBUG__
+ auto preferences = aph_->getPreferences("default");
+ auto it = preferences.find("subtitle");
+ if (it != preferences.end())
+ videoSubscriber_->setText(it->second);
+#endif
+}
+
+void
+TranscriptMediaHandler::notifyAVFrameSubject(const StreamData& data, jami::avSubjectPtr subject)
+{
+ std::ostringstream oss;
+ std::string_view direction = data.direction ? "Receive" : "Preview";
+ oss << "NEW SUBJECT: [" << data.id << "," << direction << "]" << std::endl;
+
+ accountId_ = data.source;
+ auto preferences = aph_->getPreferences(accountId_);
+
+ bool preferredStreamDirection = false; // false for output; true for input
+ auto it = preferences.find("avstream");
+ if (it != preferences.end()) {
+ preferredStreamDirection = it->second == "in";
+ }
+
+ oss << "preferredStreamDirection " << preferredStreamDirection << std::endl;
+ if (data.type == StreamType::audio && !data.direction
+ && data.direction == preferredStreamDirection) {
+ subject->attach(audioSubscriber_.get()); // your audio
+ oss << "got my sent audio attached" << std::endl;
+ attached_[0] = true ;
+ } else if (data.type == StreamType::audio && data.direction
+ && data.direction == preferredStreamDirection) {
+ subject->attach(audioSubscriber_.get()); // the audio you receive from others on the call
+ oss << "got received audio attached" << std::endl;
+ attached_[0] = true;
+ }
+
+ if (data.type == StreamType::video && !data.direction
+ && data.direction == preferredStreamDirection) {
+ subject->attach(videoSubscriber_.get()); // your video
+ oss << "got my sent video attached" << std::endl;
+ attached_[1] = true;
+ } else if (data.type == StreamType::video && data.direction
+ && data.direction == preferredStreamDirection) {
+ subject->attach(videoSubscriber_.get()); // the video you receive from others on the call
+ oss << "got received video attached" << std::endl;
+ attached_[1] = true;
+ }
+
+ Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+}
+
+void
+TranscriptMediaHandler::setParameters(const std::string& accountId)
+{
+ if (!accountId.empty() && accountId != accountId_)
+ return;
+ auto preferences = aph_->getPreferences(accountId_);
+ try {
+ videoSubscriber_->setParameter(preferences["fontsize"], Parameter::FONTSIZE);
+ videoSubscriber_->setParameter(preferences["background"], Parameter::BACKGROUND);
+ videoSubscriber_->setParameter(preferences["position"], Parameter::POSITION);
+ } catch (std::exception& e) {
+ Plog::log(Plog::LogPriority::ERR, TAG, e.what());
+ }
+}
+
+std::map<std::string, std::string>
+TranscriptMediaHandler::getCallMediaHandlerDetails()
+{
+ return {{"name", NAME},
+ {"iconPath", datapath_ + sep + "icon.svg"},
+ {"pluginId", id()},
+ {"attached", attached_[0] && attached_[1] ? "1" : "0"},
+ {"dataType", "1"}};
+}
+
+void
+TranscriptMediaHandler::detach()
+{
+ attached_ = {false, false};
+ videoSubscriber_->detach();
+ audioSubscriber_->detach();
+}
+
+TranscriptMediaHandler::~TranscriptMediaHandler()
+{
+ std::ostringstream oss;
+ oss << " ~TranscriptMediaHandler from WhisperTranscript Plugin" << std::endl;
+ Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+ detach();
+}
+} // namespace jami
diff --git a/WhisperTranscript/TranscriptMediaHandler.h b/WhisperTranscript/TranscriptMediaHandler.h
new file mode 100644
index 0000000..9191dff
--- /dev/null
+++ b/WhisperTranscript/TranscriptMediaHandler.h
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include "TranscriptAudioSubscriber.h"
+#include "TranscriptVideoSubscriber.h"
+
+#include "PluginPreferenceHandler.h"
+
+#include "plugin/jamiplugin.h"
+#include "plugin/mediahandler.h"
+
+namespace jami {
+
+class TranscriptMediaHandler : public CallMediaHandler
+{
+public:
+ TranscriptMediaHandler(std::string&& dataPath, PluginPreferenceHandler* prefHandler);
+ ~TranscriptMediaHandler();
+
+ virtual void notifyAVFrameSubject(const StreamData& data, avSubjectPtr subject) override;
+ virtual std::map<std::string, std::string> getCallMediaHandlerDetails() override;
+
+ virtual void detach() override;
+ virtual void setPreferenceAttribute(const std::string& key, const std::string& value) override {}
+ virtual bool preferenceMapHasKey(const std::string& key) override { return false; }
+
+ void setParameters(const std::string& accountId);
+
+ std::shared_ptr<TranscriptAudioSubscriber> audioSubscriber_;
+ std::shared_ptr<TranscriptVideoSubscriber> videoSubscriber_;
+
+private:
+ std::vector<bool> attached_ = {false, false};
+ std::string accountId_ {"default"};
+ const std::string datapath_;
+ PluginPreferenceHandler* aph_;
+};
+} // namespace jami
diff --git a/WhisperTranscript/TranscriptVideoSubscriber.cpp b/WhisperTranscript/TranscriptVideoSubscriber.cpp
new file mode 100644
index 0000000..d17bc2b
--- /dev/null
+++ b/WhisperTranscript/TranscriptVideoSubscriber.cpp
@@ -0,0 +1,224 @@
+/**
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "TranscriptVideoSubscriber.h"
+
+extern "C" {
+#include <libavutil/display.h>
+}
+
+#include <pluglog.h>
+#include <mediaStream.h>
+#include <frameScaler.h>
+#include <accel.h>
+#include <common.h>
+#include <frameUtils.h>
+
+#include <bitset>
+
+const std::string TAG = "Transcript";
+const char sep = separator();
+
+namespace jami {
+
+TranscriptVideoSubscriber::TranscriptVideoSubscriber(const std::string& dataPath, bool acc)
+ : path_ {dataPath}
+{
+ fontFile_ = string_utils::ffmpegFormatString(dataPath + sep + "Muli-Light.ttf");
+}
+
+TranscriptVideoSubscriber::~TranscriptVideoSubscriber()
+{
+ filter_.clean();
+ Plog::log(Plog::LogPriority::INFO, TAG, "~TranscriptMediaProcessor");
+}
+
+void
+TranscriptVideoSubscriber::setText(const std::string& text)
+{
+ subtitle_ = string_utils::ffmpegScapeString(text);
+#ifdef __DEBUG__
+ Plog::log(Plog::LogPriority::INFO, TAG, subtitle_);
+#endif
+ firstRun = true;
+}
+
+void
+TranscriptVideoSubscriber::setParameter(std::string& parameter, Parameter type)
+{
+ switch (type) {
+ case (Parameter::FONTSIZE):
+ fontSize_ = parameter;
+ break;
+ case (Parameter::BACKGROUND):
+ background_ = parameter;
+ if (background_.find("black") == std::string::npos) {
+ fontColor_ = "black";
+ fontBackground_ = "white@0.5";
+ } else {
+ fontColor_ = "white";
+ fontBackground_ = "black@0.5";
+ }
+ break;
+ case (Parameter::POSITION):
+ position_ = parameter;
+ break;
+ default:
+ return;
+ }
+
+ firstRun = true;
+}
+
+void
+TranscriptVideoSubscriber::setFilterDescription()
+{
+ if (pluginFrameSize_.first == 0 || pluginFrameSize_.second == 0)
+ return;
+
+ // 1, 2, 3, and 4 are cartesian positions
+ int margin = 10;
+ if (position_ == "1") {
+ points_[1] = {pluginFrameSize_.first - margin, margin};
+ } else if (position_ == "2") {
+ points_[1] = {margin, margin};
+ } else if (position_ == "3") {
+ points_[1] = {margin, pluginFrameSize_.second - margin};
+ } else if (position_ == "4") {
+ points_[1] = {pluginFrameSize_.first - margin, pluginFrameSize_.second - margin};
+ }
+
+ std::string rotateSides = "";
+
+ if (std::abs(angle_) == 90)
+ rotateSides = ":out_w=ih:out_h=iw";
+
+ auto baseInfosDescription = "[input]rotate=" + rotation[angle_] + rotateSides
+ + ",drawtext=fontcolor=" + fontColor_
+ + ":fontsize=" + fontSize_
+ + ":fontfile=\\'" + fontFile_
+ + "\\':expansion=none:text='" + subtitle_
+ + "':box=1:boxcolor=" + fontBackground_ + ":boxborderw=5:x=";
+ if (position_ == "1")
+ filterDescription_ = baseInfosDescription + std::to_string(points_[1].first)
+ + "-text_w:y=" + std::to_string(points_[1].second);
+ else if (position_ == "2")
+ filterDescription_ = baseInfosDescription + std::to_string(points_[1].first)
+ + ":y=" + std::to_string(points_[1].second);
+ else if (position_ == "3")
+ filterDescription_ = baseInfosDescription + std::to_string(points_[1].first)
+ + ":y=" + std::to_string(points_[1].second) + "-text_h";
+ else if (position_ == "4")
+ filterDescription_ = baseInfosDescription + std::to_string(points_[1].first)
+ + "-text_w:y=" + std::to_string(points_[1].second) + "-text_h";
+ filterDescription_ += ",rotate=" + rotation[-angle_] + rotateSides + ",format=yuv420p";
+
+#ifdef __DEBUG__
+ Plog::log(Plog::LogPriority::INFO, TAG, filterDescription_);
+#endif
+}
+
+void
+TranscriptVideoSubscriber::update(jami::Observable<AVFrame*>*, AVFrame* const& pluginFrame)
+{
+ if (!observable_ || !pluginFrame || subtitle_.empty())
+ return;
+
+ AVFrameSideData* side_data = av_frame_get_side_data(pluginFrame, AV_FRAME_DATA_DISPLAYMATRIX);
+ int newAngle {0};
+ if (side_data) {
+ auto matrix_rotation = reinterpret_cast<int32_t*>(side_data->data);
+ newAngle = static_cast<int>(av_display_rotation_get(matrix_rotation));
+ }
+ if (newAngle != angle_) {
+ angle_ = newAngle;
+ firstRun = true;
+ }
+
+ //======================================================================================
+ // GET RAW FRAME
+ uniqueFramePtr rgbFrame = {transferToMainMemory(pluginFrame, AV_PIX_FMT_NV12), frameFree};
+ rgbFrame.reset(FrameScaler::convertFormat(rgbFrame.get(), AV_PIX_FMT_YUV420P));
+ if (!rgbFrame.get())
+ return;
+
+ if (sourceTimeBase_.num != pluginFrame->time_base.num || sourceTimeBase_.den != pluginFrame->time_base.den)
+ firstRun = true;
+
+ rgbFrame->pts = pluginFrame->pts;
+ rgbFrame->time_base = pluginFrame->time_base;
+ sourceTimeBase_ = pluginFrame->time_base;
+
+ if (firstRun) {
+ filter_.clean();
+ pluginFrameSize_ = {rgbFrame->width, rgbFrame->height};
+ if (std::abs(angle_) == 90)
+ pluginFrameSize_ = {rgbFrame->height, rgbFrame->width};
+ setFilterDescription();
+
+ rational<int> fr(sourceTimeBase_.den, sourceTimeBase_.num);
+ auto ms = MediaStream("input",
+ rgbFrame->format,
+ 1 / fr,
+ rgbFrame->width,
+ rgbFrame->height,
+ 0,
+ fr);
+ filter_.initialize(filterDescription_, {ms});
+ firstRun = false;
+ }
+
+ if (!filter_.initialized_)
+ return;
+
+ if (filter_.feedInput(rgbFrame.get(), "input") == 0) {
+ uniqueFramePtr filteredFrame = {filter_.readOutput(), frameFree};
+ if (filteredFrame) {
+ moveFrom(pluginFrame, filteredFrame.get());
+ }
+ }
+}
+
+void
+TranscriptVideoSubscriber::attached(jami::Observable<AVFrame*>* observable)
+{
+ Plog::log(Plog::LogPriority::INFO, TAG, "::Attached ! ");
+ observable_ = observable;
+}
+
+void
+TranscriptVideoSubscriber::detached(jami::Observable<AVFrame*>*)
+{
+ firstRun = true;
+ observable_ = nullptr;
+ Plog::log(Plog::LogPriority::INFO, TAG, "::Detached()");
+}
+
+void
+TranscriptVideoSubscriber::detach()
+{
+ if (observable_) {
+ firstRun = true;
+ std::ostringstream oss;
+ Plog::log(Plog::LogPriority::INFO, TAG, "::Calling detach()");
+ observable_->detach(this);
+ }
+}
+} // namespace jami
diff --git a/WhisperTranscript/TranscriptVideoSubscriber.h b/WhisperTranscript/TranscriptVideoSubscriber.h
new file mode 100644
index 0000000..4d9087c
--- /dev/null
+++ b/WhisperTranscript/TranscriptVideoSubscriber.h
@@ -0,0 +1,82 @@
+/**
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+extern "C" {
+#include <libavutil/frame.h>
+}
+#include <observer.h>
+
+#include <frameFilter.h>
+
+namespace jami {
+
+enum Parameter {
+ POSITION,
+ BACKGROUND,
+ FONTSIZE,
+};
+
+class TranscriptVideoSubscriber : public Observer<AVFrame*>
+{
+public:
+ TranscriptVideoSubscriber(const std::string& dataPath, bool acc = false);
+ ~TranscriptVideoSubscriber();
+
+ virtual void update(Observable<AVFrame*>*, AVFrame* const&) override;
+ virtual void attached(Observable<AVFrame*>*) override;
+ virtual void detached(Observable<AVFrame*>*) override;
+
+ void detach();
+
+ void setText(const std::string& text);
+ void setFilterDescription();
+
+ void setParameter(std::string& parameter, Parameter type);
+
+private:
+ // Observer pattern
+ Observable<AVFrame*>* observable_{};
+
+ // Filter for video formatting
+ std::string filterDescription_;
+ FrameFilter filter_;
+ std::string subtitle_ {"No subtitle fetched."};
+ std::string fontFile_;
+ AVRational sourceTimeBase_;
+ int angle_ {0};
+ std::map<int, std::string> rotation = {{-90, "-PI/2"},
+ {90, "PI/2"},
+ {-180, "-PI"},
+ {180, "PI"},
+ {0, "0"}};
+
+ // Data
+ std::string path_;
+
+ // Status variables of the processing
+ bool firstRun {true};
+
+ std::pair<int, int> pluginFrameSize_ {0, 0};
+ std::array<std::pair<int, int>, 2> points_;
+ std::string fontSize_, background_, fontColor_, fontBackground_, position_;
+};
+} // namespace jami
diff --git a/WhisperTranscript/build.sh b/WhisperTranscript/build.sh
new file mode 100755
index 0000000..8acf280
--- /dev/null
+++ b/WhisperTranscript/build.sh
@@ -0,0 +1,419 @@
+#! /bin/bash
+# Build the plugin for the project
+set -e
+export OSTYPE
+ARCH=$(uname -m)
+EXTRAPATH=''
+# Flags:
+
+# -p: number of processors to use.
+# -c: Runtime plugin cpu/gpu setting.
+# -t: target platform.
+# -d: debug program.
+
+if [ -z "${DAEMON}" ]; then
+ DAEMON="./../../daemon"
+ echo "DAEMON not provided, building with ${DAEMON}"
+fi
+if [ -z "${PROCESSOR}" ]; then
+ PROCESSOR="CPU"
+ echo "PROCESSOR not provided, building with ${PROCESSOR}"
+fi
+
+PLUGIN_NAME="WhisperTranscript"
+JPL_FILE_NAME="${PLUGIN_NAME}.jpl"
+SO_FILE_NAME="lib${PLUGIN_NAME}.so"
+DAEMON_SRC="${DAEMON}/src"
+CONTRIB_PATH="${DAEMON}/contrib"
+PLUGINS_LIB="../lib"
+LIBS_DIR="./../contrib/Libs"
+PLATFORM=$(uname)
+
+if [ "${PLATFORM}" = "Linux" ]; then
+ PLATFORM="linux-gnu"
+ CONTRIB_PLATFORM_CURT=${ARCH}
+ echo "Building with ${PLATFORM}"
+elif [ "${PLATFORM}" = "Darwin" ]; then
+ PLATFORM="darwin"
+ SO_FILE_NAME="lib${PLUGIN_NAME}.dylib"
+ alias nproc='sysctl -n hw.logicalcpu'
+ CONTRIB_PLATFORM_CURT=${ARCH}-apple
+ CONTRIB_PLATFORM_EXTRA=$(uname -r)
+ echo "Building with ${PLATFORM}"
+fi
+
+if [ "${PROCESSOR}" = "CPU" ]; then
+ ONNX_LIBS="cpu"
+elif [ "${PROCESSOR}" = "NVIDIA" ]; then
+ ONNX_LIBS="nvidia-gpu"
+ CUBLASLT="-lcublasLt"
+fi
+
+while getopts t:c:p:d OPT; do
+ case "$OPT" in
+ d)
+ DEBUG=true
+ export __DEBUG__=true
+ ;;
+ t)
+ PLATFORM="${OPTARG}"
+ ;;
+ c)
+ PROCESSOR="${OPTARG}"
+ ;;
+ p)
+ ;;
+ \?)
+ exit 1
+ ;;
+ esac
+done
+
+cp -r ffmpeg ${CONTRIB_PATH}/src/
+cp -r ../contrib/rav1e ${CONTRIB_PATH}/src/
+
+if [ "${PLATFORM}" = "linux-gnu" ] || [ "${PLATFORM}" = "redhat-linux" ]
+then
+ if [ -f "${CONTRIB_PATH}/native/.ffmpeg" ]; then
+ rm "${CONTRIB_PATH}/native/.ffmpeg"
+ fi
+ WORKPATH=$(pwd)
+ cd "${CONTRIB_PATH}/native/"
+ make .ffmpeg -j$(nproc)
+ rm .ffmpeg
+ cd ${WORKPATH}
+
+ CONTRIB_PLATFORM=${CONTRIB_PLATFORM_CURT}-${PLATFORM}
+ ONNX_PATH=${EXTRALIBS_PATH}
+ if [ -z "${EXTRALIBS_PATH}" ]
+ then
+ ONNX_PATH="${CONTRIB_PATH}/${CONTRIB_PLATFORM}"
+ fi
+
+ if [ ${DEBUG} ]; then
+ OUTPUT="${PLUGIN_NAME}"
+ CLANG_OPTS="-g -fsanitize=address"
+ EXTRA_DEBUG_LIBRARIES="-lyaml-cpp -lvdpau -lX11 -lva-drm -lva-x11 -lrav1e"
+ EXTRA_DEFINES="-D__DEBUG__"
+ else
+ python3 ./../SDK/jplManipulation.py --preassemble --plugin=${PLUGIN_NAME}
+ CLANG_OPTS="-O3 -shared"
+ OUTPUT="build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}"
+ fi
+
+ # Compile
+ clang++ -std=c++17 -fPIC ${CLANG_OPTS} \
+ -Wl,-Bsymbolic,-rpath,"\${ORIGIN}" \
+ -Wall -Wextra \
+ -Wno-unused-parameter \
+ ${EXTRA_DEFINES} \
+ -I"." \
+ -I"${DAEMON_SRC}" \
+ -I"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/include" \
+ -I"${ONNX_PATH}/include/onnxruntime/session" \
+ -I"${ONNX_PATH}/include/onnxruntime/providers/cuda" \
+ -I"${PLUGINS_LIB}" \
+ ./../lib/common.cpp \
+ ./../lib/accel.cpp \
+ ./../lib/frameFilter.cpp \
+ ./../lib/frameUtils.cpp \
+ main.cpp \
+ TranscriptMediaHandler.cpp \
+ TranscriptAudioSubscriber.cpp \
+ TranscriptVideoSubscriber.cpp \
+ PluginPreferenceHandler.cpp \
+ Preprocess.cpp \
+ ModelProcessor.cpp \
+ -L"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/lib/" \
+ -L"${ONNX_PATH}/lib/onnxruntime/${ONNX_LIBS}" \
+ -L"${CUDA_HOME}/lib64/" \
+ -l:libavfilter.a \
+ -l:libswscale.a \
+ -l:libswresample.a \
+ -l:libavformat.a \
+ -l:libavcodec.a \
+ -l:libavutil.a \
+ -lfreetype \
+ -lvpx \
+ -lx264 \
+ -lspeex \
+ -lopus \
+ -lz \
+ -lva \
+ ${CUBLASLT} -lonnxruntime \
+ ${EXTRA_DEBUG_LIBRARIES} \
+ -o "${OUTPUT}"
+
+ if [ ${DEBUG} ]; then
+ cp "./modelSRC/mModelEncoder.onnx" "./data/assets/mModelEncoder.onnx"
+ cp "./modelSRC/mModelDecoder.onnx" "./data/assets/mModelDecoder.onnx"
+ cp "./modelSRC/mLogSoftMax.onnx" "./data/assets/mLogSoftMax.onnx"
+ cp "${ONNX_PATH}/lib/onnxruntime/${ONNX_LIBS}/libonnxruntime.so" "libonnxruntime.so.1.12.0"
+ else
+ cp "./modelSRC/mModelEncoder.onnx" "./build-local/jpl/data/assets/mModelEncoder.onnx"
+ cp "./modelSRC/mModelDecoder.onnx" "./build-local/jpl/data/assets/mModelDecoder.onnx"
+ cp "./modelSRC/mLogSoftMax.onnx" "./build-local/jpl/data/assets/mLogSoftMax.onnx"
+ cp "${ONNX_PATH}/lib/onnxruntime/${ONNX_LIBS}/libonnxruntime.so" "build-local/jpl/lib/$CONTRIB_PLATFORM/libonnxruntime.so.1.12.0"
+ fi
+ if [ "${PROCESSOR}" = "NVIDIA" ]
+ then
+ cp "${ONNX_PATH}/lib/onnxruntime/${ONNX_LIBS}/libonnxruntime_providers_shared.so" "build-local/jpl/lib/$CONTRIB_PLATFORM/libonnxruntime_providers_shared.so"
+ cp "${ONNX_PATH}/lib/onnxruntime/${ONNX_LIBS}/libonnxruntime_providers_cuda.so" "build-local/jpl/lib/$CONTRIB_PLATFORM/libonnxruntime_providers_cuda.so"
+ fi
+
+elif [ "${PLATFORM}" = "darwin" ]
+then
+ if [ -f "${CONTRIB_PATH}/native/.ffmpeg" ]; then
+ rm "${CONTRIB_PATH}/native/.ffmpeg"
+ fi
+ WORKPATH=$(pwd)
+ cd "${CONTRIB_PATH}/native/"
+ make .ffmpeg -j$(nproc)
+ rm .ffmpeg
+ cd ${WORKPATH}
+
+ CONTRIB_PLATFORM=${CONTRIB_PLATFORM_CURT}-${PLATFORM}
+ ONNX_PATH=${EXTRALIBS_PATH}
+ if [ -z "${EXTRALIBS_PATH}" ]
+ then
+ ONNX_PATH="${CONTRIB_PATH}/${CONTRIB_PLATFORM}${CONTRIB_PLATFORM_EXTRA}"
+ fi
+
+ if [ ${DEBUG} ]; then
+ OUTPUT="${PLUGIN_NAME}"
+ CLANG_OPTS="-g -fsanitize=address"
+ EXTRA_DEBUG_LIBRARIES="-lyaml-cpp -lrav1e"
+ EXTRA_DEFINES="-D__DEBUG__"
+ else
+ python3 ./../SDK/jplManipulation.py --preassemble --plugin=${PLUGIN_NAME}
+ CLANG_OPTS="-O3 -shared"
+ OUTPUT="build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}"
+ fi
+
+ # Compile
+ clang++ -std=c++17 -fPIC ${CLANG_OPTS} \
+ -Wl,-no_compact_unwind -Wl,-framework,CoreFoundation \
+ -Wl,-framework,Security -Wl,-framework,VideoToolbox \
+ -Wl,-framework,CoreMedia -Wl,-framework,CoreVideo \
+ -Wl,-framework,OpenCl -Wl,-framework,Accelerate \
+ -Wl,-rpath,"\${ORIGIN}" \
+ -Wall -Wextra \
+ -Wno-unused-parameter \
+ ${EXTRA_DEFINES} \
+ -D${PROCESSOR} \
+ -I"." \
+ -I"${DAEMON_SRC}" \
+ -I"${CONTRIB_PATH}/${CONTRIB_PLATFORM}${CONTRIB_PLATFORM_EXTRA}/include" \
+ -I"${ONNX_PATH}/include/onnxruntime/session" \
+ -I"${PLUGINS_LIB}" \
+ ./../lib/common.cpp \
+ ./../lib/accel.cpp \
+ ./../lib/frameFilter.cpp \
+ ./../lib/frameUtils.cpp \
+ main.cpp \
+ TranscriptMediaHandler.cpp \
+ TranscriptAudioSubscriber.cpp \
+ TranscriptVideoSubscriber.cpp \
+ PluginPreferenceHandler.cpp \
+ Preprocess.cpp \
+ ModelProcessor.cpp \
+ -L"${CONTRIB_PATH}/${CONTRIB_PLATFORM}${CONTRIB_PLATFORM_EXTRA}/lib/" \
+ -L"${ONNX_PATH}/lib/onnxruntime/${ONNX_LIBS}" \
+ -lavfilter \
+ -lswscale \
+ -lswresample \
+ -lavformat \
+ -lavcodec \
+ -lavutil \
+ -lvpx -lx264 -lbz2 -liconv -lz \
+ -lonnxruntime \
+ -lspeex \
+ -lopus \
+ ${EXTRA_DEBUG_LIBRARIES} \
+ -o "${OUTPUT}"
+
+ if [ ${DEBUG} ]; then
+ cp "${ONNX_PATH}/lib/onnxruntime/${ONNX_LIBS}/libonnxruntime.dylib" "libonnxruntime.dylib"
+ cp "./modelSRC/mModelEncoder.onnx" "./data/assets/mModelEncoder.onnx"
+ cp "./modelSRC/mModelDecoder.onnx" "./data/assets/mModelDecoder.onnx"
+ cp "./modelSRC/mLogSoftMax.onnx" "./data/assets/mLogSoftMax.onnx"
+ install_name_tool -id "@loader_path/libonnxruntime.1.12.0.dylib" "libonnxruntime.dylib"
+ install_name_tool -id "@loader_path/${PLUGIN_NAME}" "${OUTPUT}"
+ else
+ cp "./modelSRC/mModelEncoder.onnx" "./build-local/jpl/data/assets/mModelEncoder.onnx"
+ cp "./modelSRC/mModelDecoder.onnx" "./build-local/jpl/data/assets/mModelDecoder.onnx"
+ cp "./modelSRC/mLogSoftMax.onnx" "./build-local/jpl/data/assets/mLogSoftMax.onnx"
+ cp "${ONNX_PATH}/lib/onnxruntime/${ONNX_LIBS}/libonnxruntime.dylib" "build-local/jpl/lib/${CONTRIB_PLATFORM}/libonnxruntime.dylib"
+ install_name_tool -id "@loader_path/libonnxruntime.1.12.0.dylib" "build-local/jpl/lib/${CONTRIB_PLATFORM}/libonnxruntime.dylib"
+ install_name_tool -id "@loader_path/${SO_FILE_NAME}" "${OUTPUT}"
+ fi
+ install_name_tool -change "@rpath/libonnxruntime.1.12.0.dylib" "@loader_path/libonnxruntime.dylib" "${OUTPUT}"
+
+ if [ -n "${APPLE_SIGN_CERTIFICATE}" ]; then
+ codesign --force --verify --timestamp -o runtime --sign "${APPLE_SIGN_CERTIFICATE}" "build-local/jpl/lib/${CONTRIB_PLATFORM}/libonnxruntime.dylib"
+ codesign --force --verify --timestamp -o runtime --sign "${APPLE_SIGN_CERTIFICATE}" "build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}"
+ ditto -c -k --rsrc "build-local/jpl/lib/${CONTRIB_PLATFORM}/libonnxruntime.dylib" "build-local/libonnxruntime.dylib.zip"
+ LIBRARYNAME=libonnxruntime.dylib sh ./../notarize.sh
+ ditto -x -k "build-local/libonnxruntime.dylib.zip" "build-local/notarized0"
+ cp "build-local/notarized0/libonnxruntime.dylib" "build-local/jpl/lib/${CONTRIB_PLATFORM}/libonnxruntime.dylib"
+
+ ditto -c -k --rsrc "build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}" "build-local/${SO_FILE_NAME}.zip"
+ LIBRARYNAME=${SO_FILE_NAME} sh ./../notarize.sh
+ ditto -x -k "build-local/${SO_FILE_NAME}.zip" "build-local/notarized1"
+ cp "build-local/notarized1/${SO_FILE_NAME}" "build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}"
+ fi
+
+elif [ "${PLATFORM}" = "android" ]
+then
+ python3 ./../SDK/jplManipulation.py --preassemble --plugin=${PLUGIN_NAME} --distribution=${PLATFORM}
+
+ if [ -z "$ANDROID_NDK" ]; then
+ ANDROID_NDK="/home/${USER}/Android/Sdk/ndk/21.1.6352462"
+ echo "ANDROID_NDK not provided, building with ${ANDROID_NDK}"
+ fi
+
+ #=========================================================
+ # Check if the ANDROID_ABI was provided
+ # if not, set default
+ #=========================================================
+ if [ -z "$ANDROID_ABI" ]; then
+ ANDROID_ABI="armeabi-v7a arm64-v8a x86_64"
+ echo "ANDROID_ABI not provided, building for ${ANDROID_ABI}"
+ fi
+
+ buildlib() {
+ echo "$CURRENT_ABI"
+
+ #=========================================================
+ # ANDROID TOOLS
+ #=========================================================
+ export HOST_TAG=linux-x86_64
+ export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/$HOST_TAG
+ export AR=$TOOLCHAIN/bin/llvm-ar
+ export AS=$TOOLCHAIN/bin/llvm-as
+ export LD=$TOOLCHAIN/bin/ld
+ export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
+ export STRIP=$TOOLCHAIN/bin/llvm-strip
+ export ANDROID_SYSROOT=$TOOLCHAIN/sysroot
+
+ if [ "$CURRENT_ABI" = armeabi-v7a ]
+ then
+ export CC=$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang
+ export CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang++
+
+ elif [ "$CURRENT_ABI" = arm64-v8a ]
+ then
+ export CC=$TOOLCHAIN/bin/aarch64-linux-android21-clang
+ export CXX=$TOOLCHAIN/bin/aarch64-linux-android21-clang++
+
+ elif [ "$CURRENT_ABI" = x86_64 ]
+ then
+ export CC=$TOOLCHAIN/bin/x86_64-linux-android21-clang
+ export CXX=$TOOLCHAIN/bin/x86_64-linux-android21-clang++
+
+ else
+ echo "ABI NOT OK" >&2
+ exit 1
+ fi
+
+ #=========================================================
+ # CONTRIBS
+ #=========================================================
+ if [ "$CURRENT_ABI" = armeabi-v7a ]
+ then
+ CONTRIB_PLATFORM=arm-linux-androideabi
+
+ elif [ "$CURRENT_ABI" = arm64-v8a ]
+ then
+ CONTRIB_PLATFORM=aarch64-linux-android
+
+ elif [ "$CURRENT_ABI" = x86_64 ]
+ then
+ CONTRIB_PLATFORM=x86_64-linux-android
+ fi
+
+ if [ -f "${CONTRIB_PATH}/native-${CONTRIB_PLATFORM}/.ffmpeg" ]; then
+ rm "${CONTRIB_PATH}/native-${CONTRIB_PLATFORM}/.ffmpeg"
+ fi
+
+ WORKPATH=$(pwd)
+ cd "${CONTRIB_PATH}/native-${CONTRIB_PLATFORM}/"
+ make .ffmpeg -j$(nproc)
+ rm .ffmpeg
+ cd ${WORKPATH}
+
+ #=========================================================
+ # Compile the plugin
+ #=========================================================
+
+ ONNX_PATH="${EXTRALIBS_PATH}/${CURRENT_ABI}"
+ if [ -z ${EXTRALIBS_PATH} ]
+ then
+ ONNX_PATH="${CONTRIB_PATH}/${CONTRIB_PLATFORM}"
+ fi
+
+ # Create so destination folder
+ $CXX --std=c++17 -O3 -fPIC \
+ -Wl,-Bsymbolic,-rpath,"\${ORIGIN}" \
+ -shared \
+ -Wall -Wextra \
+ -Wno-unused-parameter \
+ -DANDROID \
+ -I"." \
+ -I"${DAEMON_SRC}" \
+ -I"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/include" \
+ -I"${ONNX_PATH}/include/onnxruntime/session" \
+ -I"${ONNX_PATH}/include/onnxruntime/providers/nnapi" \
+ -I"${ONNX_PATH}/../include/onnxruntime/session" \
+ -I"${ONNX_PATH}/../include/onnxruntime/providers/nnapi" \
+ -I"${PLUGINS_LIB}" \
+ ./../lib/common.cpp \
+ ./../lib/accel.cpp \
+ ./../lib/frameFilter.cpp \
+ ./../lib/frameUtils.cpp \
+ main.cpp \
+ TranscriptMediaHandler.cpp \
+ TranscriptAudioSubscriber.cpp \
+ TranscriptVideoSubscriber.cpp \
+ PluginPreferenceHandler.cpp \
+ Preprocess.cpp \
+ ModelProcessor.cpp \
+ -L"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/lib/" \
+ -L"${ONNX_PATH}/lib/" \
+ -lavfilter \
+ -lswscale \
+ -lswresample \
+ -lavformat \
+ -lavcodec \
+ -lavutil \
+ -lvpx \
+ -lx264 \
+ -lspeex \
+ -lopus \
+ -llog -lz \
+ -lonnxruntime \
+ --sysroot=$ANDROID_SYSROOT \
+ -o "build-local/jpl/lib/$CURRENT_ABI/${SO_FILE_NAME}"
+
+ cp "${ONNX_PATH}/lib/libonnxruntime.so" "build-local/jpl/lib/${CURRENT_ABI}/libonnxruntime.so"
+ }
+
+ # Build the so
+ for i in ${ANDROID_ABI}; do
+ CURRENT_ABI=$i
+ buildlib
+ done
+
+ cp "./modelSRC/mModelEncoder.ort" "./build-local/jpl/data/assets/mModelEncoder.ort"
+ cp "./modelSRC/mModelDecoder.ort" "./build-local/jpl/data/assets/mModelDecoder.ort"
+ cp "./modelSRC/mLogSoftMax.ort" "./build-local/jpl/data/assets/mLogSoftMax.ort"
+fi
+
+if [ ! ${DEBUG} ]; then
+ python3 ./../SDK/jplManipulation.py --assemble --plugin=${PLUGIN_NAME} --distribution=${PLATFORM} --extraPath=${EXTRAPATH}
+fi
+
+cd ${CONTRIB_PATH}/src/ffmpeg/
+# ffmpeg build configuration files were changed during plugin build
+# this git checkout will remove these changes
+git checkout -- .
diff --git a/WhisperTranscript/data/Muli-Light.ttf b/WhisperTranscript/data/Muli-Light.ttf
new file mode 100644
index 0000000..0ffcfba
--- /dev/null
+++ b/WhisperTranscript/data/Muli-Light.ttf
Binary files differ
diff --git a/WhisperTranscript/data/accountpreferences.json b/WhisperTranscript/data/accountpreferences.json
new file mode 100644
index 0000000..a5a6a36
--- /dev/null
+++ b/WhisperTranscript/data/accountpreferences.json
@@ -0,0 +1,10 @@
+[
+ {
+ "type": "Switch",
+ "key": "TranscriptAlways",
+ "title": "{{TranscriptAlways_title}}",
+ "summary": "{{TranscriptAlways_summary}}",
+ "defaultValue": "1",
+ "scope": "plugin"
+ }
+]
\ No newline at end of file
diff --git a/WhisperTranscript/data/assets/.gitignore b/WhisperTranscript/data/assets/.gitignore
new file mode 100644
index 0000000..e1a699a
--- /dev/null
+++ b/WhisperTranscript/data/assets/.gitignore
@@ -0,0 +1 @@
+*.onnx
diff --git a/WhisperTranscript/data/assets/mel_filters.bin b/WhisperTranscript/data/assets/mel_filters.bin
new file mode 100644
index 0000000..9e3c32b
--- /dev/null
+++ b/WhisperTranscript/data/assets/mel_filters.bin
Binary files differ
diff --git a/WhisperTranscript/data/assets/tokenizer.bin b/WhisperTranscript/data/assets/tokenizer.bin
new file mode 100644
index 0000000..e858463
--- /dev/null
+++ b/WhisperTranscript/data/assets/tokenizer.bin
Binary files differ
diff --git a/WhisperTranscript/data/icon.svg b/WhisperTranscript/data/icon.svg
new file mode 100644
index 0000000..326b0fe
--- /dev/null
+++ b/WhisperTranscript/data/icon.svg
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="300px" height="300px" viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <title>P</title>
+ <defs>
+ <linearGradient x1="-0.0143679903%" y1="50%" x2="99.9840558%" y2="50%" id="linearGradient-1">
+ <stop stop-color="#181844" offset="0%"></stop>
+ <stop stop-color="#1E1E4C" offset="2.84%"></stop>
+ <stop stop-color="#283261" offset="13.53%"></stop>
+ <stop stop-color="#2D4172" offset="24.68%"></stop>
+ <stop stop-color="#2E4A7C" offset="36.47%"></stop>
+ <stop stop-color="#2E4D7F" offset="50%"></stop>
+ <stop stop-color="#2D4576" offset="61.77%"></stop>
+ <stop stop-color="#273160" offset="81.25%"></stop>
+ <stop stop-color="#181844" offset="100%"></stop>
+ </linearGradient>
+ <linearGradient x1="-0.0143775661%" y1="50.0132404%" x2="99.9808363%" y2="50.0132404%" id="linearGradient-2">
+ <stop stop-color="#2867A2" offset="0%"></stop>
+ <stop stop-color="#2174B1" offset="3.82%"></stop>
+ <stop stop-color="#0B86C4" offset="11.77%"></stop>
+ <stop stop-color="#0A94D2" offset="20.81%"></stop>
+ <stop stop-color="#0C9BDB" offset="31.77%"></stop>
+ <stop stop-color="#109EDE" offset="50%"></stop>
+ <stop stop-color="#0C9BDB" offset="68.23%"></stop>
+ <stop stop-color="#0A94D2" offset="79.19%"></stop>
+ <stop stop-color="#0B86C4" offset="88.23%"></stop>
+ <stop stop-color="#2174B1" offset="96.18%"></stop>
+ <stop stop-color="#2867A2" offset="100%"></stop>
+ </linearGradient>
+ </defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="P" transform="translate(34.000000, 0.000000)">
+ <path d="M115.654206,0.0700934579 C51.7990654,0.0700934579 0.0700934579,51.8691589 0.0700934579,115.724299 L0.0700934579,299.929907 L80.3971963,299.929907 L80.3971963,225.841121 C91.5420561,229.415888 103.38785,231.378505 115.724299,231.378505 C179.579439,231.378505 231.308411,179.649533 231.308411,115.794393 C231.238318,51.8691589 179.509346,0.0700934579 115.654206,0.0700934579 Z M115.654206,151.051402 C96.1682243,151.051402 80.3271028,135.21028 80.3271028,115.724299 C80.3271028,96.2383178 96.1682243,80.3971963 115.654206,80.3971963 C135.140187,80.3971963 150.981308,96.2383178 150.981308,115.724299 C150.981308,135.21028 135.140187,151.051402 115.654206,151.051402 Z" id="Shape" fill="url(#linearGradient-1)"></path>
+ <path d="M133.247664,1.40186916 C133.247664,1.40186916 198.785047,18.9252336 193.808411,80.3971963 C188.831776,141.799065 137.663551,149.299065 105.490654,150.981308 C73.317757,152.663551 0.0700934579,159.462617 0.0700934579,242.803738 C0.0700934579,242.803738 29.8598131,210.490654 80.3971963,225.771028 C126.168224,239.579439 174.462617,225 202.219626,192.336449 C228.85514,160.934579 238.037383,123.014019 225.841121,80.3271028 C213.785047,38.4813084 173.971963,6.93925234 133.247664,1.40186916 Z" id="Path" fill="url(#linearGradient-2)"></path>
+ </g>
+ </g>
+</svg>
\ No newline at end of file
diff --git a/WhisperTranscript/data/locale/WhisperTranscript_en.json b/WhisperTranscript/data/locale/WhisperTranscript_en.json
new file mode 100644
index 0000000..b6beff2
--- /dev/null
+++ b/WhisperTranscript/data/locale/WhisperTranscript_en.json
@@ -0,0 +1,20 @@
+{
+ "avstream_title": "Stream",
+ "avstream_summary": "Select the stream to process the transcription",
+ "avstream_entries_1": "Sent",
+ "avstream_entries_2": "Received",
+ "TranscriptAlways_title": "Automatically activate transcription",
+ "TranscriptAlways_summary": "Activate transcription when a call starts.",
+ "background_title": "Add background color",
+ "background_summary": "Add a partial transparency to the subtitle background if it isn't visible enough",
+ "background_entries_1": "None",
+ "background_entries_2": "Black",
+ "background_entries_3": "White",
+ "position_title": "Transcription position",
+ "position_entries_1": "Top right",
+ "position_entries_2": "Top left",
+ "position_entries_3": "Bottom left",
+ "position_entries_4": "Bottom right",
+ "fontsize_title": "Font size"
+
+}
\ No newline at end of file
diff --git a/WhisperTranscript/data/preferences.json b/WhisperTranscript/data/preferences.json
new file mode 100644
index 0000000..e5fd3d5
--- /dev/null
+++ b/WhisperTranscript/data/preferences.json
@@ -0,0 +1,82 @@
+[
+ {
+ "type": "List",
+ "key": "background",
+ "title": "{{background_title}}",
+ "summary": "{{background_summary}}",
+ "defaultValue": "black@0.0",
+ "scope": "plugin,Transcript",
+ "entryValues": [
+ "black@0.0",
+ "black@0.5",
+ "white@0.5"
+ ],
+ "entries": [
+ "{{background_entries_1}}",
+ "{{background_entries_2}}",
+ "{{background_entries_3}}"
+ ]
+ },
+ {
+ "type": "List",
+ "key": "position",
+ "title": "{{position_title}}",
+ "defaultValue": "2",
+ "scope": "plugin,Transcript",
+ "entryValues": [
+ "1",
+ "2",
+ "3",
+ "4"
+ ],
+ "entries": [
+ "{{position_entries_1}}",
+ "{{position_entries_2}}",
+ "{{position_entries_3}}",
+ "{{position_entries_4}}"
+ ]
+ },
+ {
+ "type": "List",
+ "key": "fontsize",
+ "title": "{{fontsize_title}}",
+ "defaultValue": "14",
+ "scope": "plugin,Transcript",
+ "entryValues": [
+ "10",
+ "12",
+ "14",
+ "16",
+ "18",
+ "24",
+ "36",
+ "72"
+ ],
+ "entries": [
+ "10",
+ "12",
+ "14",
+ "16",
+ "18",
+ "24",
+ "36",
+ "72"
+ ]
+ },
+ {
+ "type": "List",
+ "key": "avstream",
+ "title": "{{avstream_title}}",
+ "summary": "{{avstream_summary}}",
+ "defaultValue": "in",
+ "scope": "plugin",
+ "entryValues": [
+ "out",
+ "in"
+ ],
+ "entries": [
+ "{{avstream_entries_1}}",
+ "{{avstream_entries_2}}"
+ ]
+ }
+]
\ No newline at end of file
diff --git a/WhisperTranscript/ffmpeg/package.json b/WhisperTranscript/ffmpeg/package.json
new file mode 100644
index 0000000..69c2a52
--- /dev/null
+++ b/WhisperTranscript/ffmpeg/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "ffmpeg",
+ "version": "n5.0",
+ "url": "https://git.ffmpeg.org/gitweb/ffmpeg.git/snapshot/__VERSION__.tar.gz",
+ "deps": [
+ "vpx",
+ "x264",
+ "opus",
+ "ffnvcodec",
+ "media-sdk"
+ ],
+ "patches": [
+ "change-RTCP-ratio.patch",
+ "rtp_ext_abs_send_time.patch",
+ "libopusenc-reload-packet-loss-at-encode.patch",
+ "libopusdec-enable-FEC.patch",
+ "windows-configure.patch",
+ "windows-configure-ffnvcodec.patch",
+ "windows-configure-libmfx.patch"
+ ],
+ "win_patches": [
+ ],
+ "project_paths": [],
+ "with_env" : "10.0.16299.0",
+ "custom_scripts": {
+ "pre_build": [],
+ "build": [
+ "call \"%CONTRIB_SRC_DIR%\\ffmpeg\\build_ffmpeg.bat\"",
+ "cd Build/win32/x64/lib & ren *.a *.lib"
+ ],
+ "post_build": []
+ }
+}
diff --git a/WhisperTranscript/ffmpeg/rules.mak b/WhisperTranscript/ffmpeg/rules.mak
new file mode 100644
index 0000000..7b5c554
--- /dev/null
+++ b/WhisperTranscript/ffmpeg/rules.mak
@@ -0,0 +1,365 @@
+FFMPEG_HASH := n5.0
+FFMPEG_URL := https://git.ffmpeg.org/gitweb/ffmpeg.git/snapshot/$(FFMPEG_HASH).tar.gz
+
+PKGS+=ffmpeg
+
+ifdef HAVE_ANDROID
+DEPS_ffmpeg = iconv zlib vpx opus speex x264 freetype
+else
+ifdef __DEBUG__
+DEPS_ffmpeg = iconv zlib vpx opus speex x264 rav1e
+else
+DEPS_ffmpeg = iconv zlib vpx opus speex x264
+endif
+endif
+
+FFMPEGCONF = \
+ --cc="$(CC)" \
+ --pkg-config="$(PKG_CONFIG)"
+
+#disable everything
+FFMPEGCONF += \
+ --disable-everything \
+ --enable-zlib \
+ --enable-gpl \
+ --enable-swscale \
+ --enable-bsfs \
+ --disable-filters \
+ --disable-programs \
+ --disable-postproc
+
+FFMPEGCONF += \
+ --disable-protocols \
+ --enable-protocol=crypto \
+ --enable-protocol=file \
+ --enable-protocol=rtp \
+ --enable-protocol=srtp \
+ --enable-protocol=tcp \
+ --enable-protocol=udp \
+ --enable-protocol=unix \
+ --enable-protocol=pipe
+
+#enable muxers/demuxers
+FFMPEGCONF += \
+ --disable-demuxers \
+ --disable-muxers \
+ --enable-muxer=rtp \
+ --enable-muxer=g722 \
+ --enable-muxer=h263 \
+ --enable-muxer=h264 \
+ --enable-muxer=hevc \
+ --enable-muxer=webm \
+ --enable-muxer=ogg \
+ --enable-muxer=pcm_s16be \
+ --enable-muxer=pcm_s16le \
+ --enable-muxer=wav \
+ --enable-muxer=w64 \
+ --enable-demuxer=rtp \
+ --enable-demuxer=mjpeg \
+ --enable-demuxer=mjpeg_2000 \
+ --enable-demuxer=mpegvideo \
+ --enable-demuxer=gif \
+ --enable-demuxer=image_jpeg_pipe \
+ --enable-demuxer=image_png_pipe \
+ --enable-demuxer=image_webp_pipe \
+ --enable-demuxer=matroska \
+ --enable-demuxer=m4v \
+ --enable-demuxer=ogg \
+ --enable-demuxer=flac \
+ --enable-demuxer=wav \
+ --enable-demuxer=w64 \
+ --enable-demuxer=ac3 \
+ --enable-demuxer=g722 \
+ --enable-demuxer=pcm_mulaw \
+ --enable-demuxer=pcm_alaw \
+ --enable-demuxer=pcm_s16be \
+ --enable-demuxer=pcm_s16le \
+ --enable-demuxer=h263 \
+ --enable-demuxer=h264 \
+ --enable-demuxer=hevc
+
+#enable parsers
+FFMPEGCONF += \
+ --enable-parser=h263 \
+ --enable-parser=h264 \
+ --enable-parser=hevc \
+ --enable-parser=mpeg4video \
+ --enable-parser=vp8 \
+ --enable-parser=vp9 \
+ --enable-parser=opus \
+ --enable-parser=w64 \
+ --enable-parser=wav
+
+#encoders/decoders
+FFMPEGCONF += \
+ --enable-encoder=w64 \
+ --enable-encoder=wav \
+ --enable-decoder=w64 \
+ --enable-decoder=wav \
+ --enable-encoder=adpcm_g722 \
+ --enable-decoder=adpcm_g722 \
+ --enable-encoder=rawvideo \
+ --enable-decoder=rawvideo \
+ --enable-encoder=libx264 \
+ --enable-decoder=h264 \
+ --enable-encoder=pcm_alaw \
+ --enable-decoder=pcm_alaw \
+ --enable-encoder=pcm_mulaw \
+ --enable-decoder=pcm_mulaw \
+ --enable-encoder=mpeg4 \
+ --enable-decoder=mpeg4 \
+ --enable-encoder=libvpx_vp8 \
+ --enable-decoder=vp8 \
+ --enable-decoder=vp9 \
+ --enable-encoder=h263 \
+ --enable-encoder=h263p \
+ --enable-decoder=h263 \
+ --enable-encoder=mjpeg \
+ --enable-decoder=mjpeg \
+ --enable-decoder=mjpegb \
+ --enable-libspeex \
+ --enable-libopus \
+ --enable-libvpx \
+ --enable-libx264 \
+ --enable-encoder=libspeex \
+ --enable-decoder=libspeex \
+ --enable-encoder=libopus \
+ --enable-decoder=libopus
+
+ifdef __DEBUG__
+FFMPEGCONF += \
+ --enable-librav1e \
+ --enable-encoder=librav1e \
+ --enable-muxer=mp4
+endif
+
+# decoders for ringtones and audio streaming
+FFMPEGCONF += \
+ --enable-decoder=flac \
+ --enable-decoder=vorbis \
+ --enable-decoder=aac \
+ --enable-decoder=ac3 \
+ --enable-decoder=eac3 \
+ --enable-decoder=pcm_u24be \
+ --enable-decoder=pcm_u24le \
+ --enable-decoder=pcm_u32be \
+ --enable-decoder=pcm_u32le \
+ --enable-decoder=pcm_u8 \
+ --enable-decoder=pcm_f16le \
+ --enable-decoder=pcm_f24le \
+ --enable-decoder=pcm_f32be \
+ --enable-decoder=pcm_f32le \
+ --enable-decoder=pcm_f64be \
+ --enable-decoder=pcm_f64le \
+ --enable-decoder=pcm_s16be \
+ --enable-decoder=pcm_s16be_planar \
+ --enable-decoder=pcm_s16le \
+ --enable-decoder=pcm_s16le_planar \
+ --enable-decoder=pcm_s24be \
+ --enable-decoder=pcm_s24le \
+ --enable-decoder=pcm_s24le_planar \
+ --enable-decoder=pcm_s32be \
+ --enable-decoder=pcm_s32le \
+ --enable-decoder=pcm_s32le_planar \
+ --enable-decoder=pcm_s64be \
+ --enable-decoder=pcm_s64le \
+ --enable-decoder=pcm_s8 \
+ --enable-decoder=pcm_s8_planar \
+ --enable-decoder=pcm_u16be \
+ --enable-decoder=pcm_u16le
+
+#filters
+FFMPEGCONF += \
+ --enable-filter=scale \
+ --enable-filter=aresample \
+ --enable-filter=aformat \
+ --enable-filter=rotate \
+ --enable-filter=format \
+ --enable-filter=drawbox \
+ --enable-filter=drawtext \
+ --enable-libfreetype
+
+#platform specific options
+
+ifdef HAVE_WIN32
+FFMPEGCONF += \
+ --enable-indev=dshow \
+ --enable-indev=gdigrab \
+ --enable-dxva2
+endif
+
+ifdef HAVE_LINUX
+FFMPEGCONF += --enable-pic
+ifdef HAVE_ANDROID
+# Android Linux
+FFMPEGCONF += \
+ --target-os=android \
+ --enable-jni \
+ --enable-mediacodec \
+ --disable-vulkan \
+ --enable-decoder=vp8_mediacodec \
+ --enable-decoder=h264_mediacodec \
+ --enable-decoder=mpeg4_mediacodec \
+ --enable-decoder=hevc_mediacodec \
+ --enable-cross-compile \
+ --ranlib=$(RANLIB) \
+ --strip=$(STRIP) \
+ --cc=$(CC) \
+ --cxx=$(CXX) \
+ --ld=$(CC) \
+ --ar=$(AR)
+# ASM not working on Android x86 https://trac.ffmpeg.org/ticket/4928
+ifeq ($(ARCH),i386)
+FFMPEGCONF += --disable-asm
+endif
+ifeq ($(ARCH),x86_64)
+FFMPEGCONF += --disable-asm
+endif
+else
+# Desktop Linux
+DEPS_ffmpeg += ffnvcodec
+FFMPEGCONF += \
+ --target-os=linux \
+ --enable-indev=v4l2 \
+ --enable-indev=xcbgrab \
+ --enable-vdpau \
+ --enable-hwaccel=h264_vdpau \
+ --enable-hwaccel=mpeg4_vdpau \
+ --enable-vaapi \
+ --enable-hwaccel=h264_vaapi \
+ --enable-hwaccel=mpeg4_vaapi \
+ --enable-hwaccel=h263_vaapi \
+ --enable-hwaccel=vp8_vaapi \
+ --enable-hwaccel=mjpeg_vaapi \
+ --enable-hwaccel=hevc_vaapi \
+ --enable-encoder=h264_vaapi \
+ --enable-encoder=vp8_vaapi \
+ --enable-encoder=mjpeg_vaapi \
+ --enable-encoder=hevc_vaapi
+# ffnvcodec is not supported on ARM then we enable it here for i386 and x86_64
+ifeq ($(ARCH),$(filter $(ARCH),i386 x86_64))
+FFMPEGCONF += --enable-cuvid \
+ --enable-ffnvcodec \
+ --enable-nvdec \
+ --enable-nvenc \
+ --enable-hwaccel=h264_nvdec \
+ --enable-hwaccel=hevc_nvdec \
+ --enable-hwaccel=vp8_nvdec \
+ --enable-hwaccel=mjpeg_nvdec \
+ --enable-encoder=h264_nvenc \
+ --enable-encoder=hevc_nvenc
+endif
+# End Desktop Linux:
+endif
+# End HAVE_LINUX:
+endif
+
+ifdef HAVE_MACOSX
+FFMPEGCONF += \
+ --enable-avfoundation \
+ --enable-indev=avfoundation \
+ --enable-videotoolbox \
+ --enable-hwaccel=h263_videotoolbox \
+ --enable-hwaccel=h264_videotoolbox \
+ --enable-hwaccel=mpeg4_videotoolbox \
+ --enable-hwaccel=hevc_videotoolbox \
+ --enable-encoder=h264_videotoolbox \
+ --enable-encoder=hevc_videotoolbox \
+ --disable-securetransport
+endif
+
+ifdef HAVE_IOS
+FFMPEGCONF += \
+ --enable-videotoolbox \
+ --enable-hwaccel=h263_videotoolbox \
+ --enable-hwaccel=h264_videotoolbox \
+ --enable-hwaccel=mpeg4_videotoolbox \
+ --enable-hwaccel=hevc_videotoolbox \
+ --enable-encoder=h264_videotoolbox \
+ --enable-encoder=hevc_videotoolbox \
+ --target-os=darwin \
+ --enable-cross-compile \
+ --enable-pic
+endif
+
+ifndef HAVE_IOS
+ifndef HAVE_ANDROID
+ifdef HAVE_CROSS_COMPILE
+FFMPEGCONF += --cross-prefix=$(HOST)-
+endif
+endif
+endif
+
+# x86 stuff
+ifeq ($(ARCH),i386)
+FFMPEGCONF += --arch=x86
+endif
+
+ifeq ($(ARCH),x86_64)
+FFMPEGCONF += --arch=x86_64
+endif
+
+# ARM stuff
+ifeq ($(ARCH),arm)
+FFMPEGCONF += --arch=arm
+ifdef HAVE_ARMV7A
+FFMPEGCONF += --cpu=cortex-a8
+endif
+ifdef HAVE_ARMV6
+FFMPEGCONF += --cpu=armv6 --disable-neon
+endif
+endif
+
+# ARM64 stuff
+ifeq ($(ARCH),aarch64)
+FFMPEGCONF += --arch=aarch64
+endif
+ifeq ($(ARCH),arm64)
+FFMPEGCONF += --arch=aarch64
+endif
+
+# Windows
+ifdef HAVE_WIN32
+DEPS_ffmpeg += ffnvcodec
+FFMPEGCONF += --target-os=mingw32 \
+ --enable-w32threads \
+ --disable-decoder=dca \
+ --enable-cuvid \
+ --enable-ffnvcodec \
+ --enable-nvdec \
+ --enable-nvenc \
+ --enable-hwaccel=h264_nvdec \
+ --enable-hwaccel=hevc_nvdec \
+ --enable-hwaccel=vp8_nvdec \
+ --enable-hwaccel=mjpeg_nvdec \
+ --enable-encoder=h264_nvenc \
+ --enable-encoder=hevc_nvenc
+endif
+
+$(TARBALLS)/ffmpeg-$(FFMPEG_HASH).tar.gz:
+ $(call download,$(FFMPEG_URL))
+
+.sum-ffmpeg: ffmpeg-$(FFMPEG_HASH).tar.gz
+
+ffmpeg: ffmpeg-$(FFMPEG_HASH).tar.gz
+ rm -Rf $@ $@-$(FFMPEG_HASH)
+ mkdir -p $@-$(FFMPEG_HASH)
+ (cd $@-$(FFMPEG_HASH) && tar x $(if ${BATCH_MODE},,-v) --strip-components=1 -f ../$<)
+ $(APPLY) $(SRC)/ffmpeg/remove-mjpeg-log.patch
+ $(APPLY) $(SRC)/ffmpeg/change-RTCP-ratio.patch
+ $(APPLY) $(SRC)/ffmpeg/rtp_ext_abs_send_time.patch
+ $(APPLY) $(SRC)/ffmpeg/libopusdec-enable-FEC.patch
+ $(APPLY) $(SRC)/ffmpeg/libopusenc-reload-packet-loss-at-encode.patch
+ $(APPLY) $(SRC)/ffmpeg/ios-disable-b-frames.patch
+ $(APPLY) $(SRC)/ffmpeg/screen-sharing-x11-fix.patch
+ $(UPDATE_AUTOCONFIG)
+ $(MOVE)
+
+.ffmpeg: ffmpeg .sum-ffmpeg
+ cd $< && $(HOSTVARS) ./configure \
+ --extra-cflags="$(CFLAGS)" \
+ --extra-ldflags="$(LDFLAGS)" $(FFMPEGCONF) \
+ --prefix="$(PREFIX)" --enable-static --disable-shared \
+ --pkg-config-flags="--static"
+ cd $< && $(MAKE) install-libs install-headers
+ touch $@
diff --git a/WhisperTranscript/ffmpeg/windows-configure-make.sh b/WhisperTranscript/ffmpeg/windows-configure-make.sh
new file mode 100644
index 0000000..dbd4ae0
--- /dev/null
+++ b/WhisperTranscript/ffmpeg/windows-configure-make.sh
@@ -0,0 +1,183 @@
+#!/bin/bash
+set +x
+set +e
+DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+cd $DIR/../../build/ffmpeg
+FFMPEGCONF='
+ --toolchain=msvc
+ --target-os=win32'
+
+#disable everything
+FFMPEGCONF+='
+ --disable-everything
+ --disable-programs
+ --disable-d3d11va
+ --disable-dxva2
+ --disable-postproc
+ --disable-filters'
+
+FFMPEGCONF+='
+ --enable-cross-compile
+ --enable-gpl
+ --enable-swscale
+ --enable-protocols
+ --enable-bsfs'
+
+#enable muxers/demuxers
+FFMPEGCONF+='
+ --enable-demuxers
+ --enable-muxers
+ --enable-muxer=mp4'
+
+#enable parsers
+FFMPEGCONF+='
+ --enable-parser=h263
+ --enable-parser=h264
+ --enable-parser=hevc
+ --enable-parser=mpeg4video
+ --enable-parser=vp8
+ --enable-parser=vp9
+ --enable-parser=opus'
+
+#encoders/decoders
+FFMPEGCONF+='
+ --enable-libopus
+ --enable-encoder=libopus
+ --enable-decoder=libopus
+ --enable-encoder=adpcm_g722
+ --enable-decoder=adpcm_g722
+ --enable-encoder=pcm_alaw
+ --enable-decoder=pcm_alaw
+ --enable-encoder=pcm_mulaw
+ --enable-decoder=pcm_mulaw
+ --enable-libx264
+ --enable-encoder=libx264
+ --enable-decoder=h264
+ --enable-encoder=rawvideo
+ --enable-decoder=rawvideo
+ --enable-encoder=mpeg4
+ --enable-decoder=mpeg4
+ --enable-encoder=h263
+ --enable-encoder=h263p
+ --enable-decoder=h263
+ --enable-encoder=mjpeg
+ --enable-decoder=mjpeg
+ --enable-decoder=mjpegb'
+
+# decoders for ringtones and audio streaming
+FFMPEGCONF+='
+ --enable-decoder=flac
+ --enable-decoder=vorbis
+ --enable-decoder=aac
+ --enable-decoder=ac3
+ --enable-decoder=eac3
+ --enable-decoder=pcm_u24be
+ --enable-decoder=pcm_u24le
+ --enable-decoder=pcm_u32be
+ --enable-decoder=pcm_u32le
+ --enable-decoder=pcm_u8
+ --enable-decoder=pcm_f16le
+ --enable-decoder=pcm_f24le
+ --enable-decoder=pcm_f32be
+ --enable-decoder=pcm_f32le
+ --enable-decoder=pcm_f64be
+ --enable-decoder=pcm_f64le
+ --enable-decoder=pcm_s16be
+ --enable-decoder=pcm_s16be_planar
+ --enable-decoder=pcm_s16le
+ --enable-decoder=pcm_s16le_planar
+ --enable-decoder=pcm_s24be
+ --enable-decoder=pcm_s24le
+ --enable-decoder=pcm_s24le_planar
+ --enable-decoder=pcm_s32be
+ --enable-decoder=pcm_s32le
+ --enable-decoder=pcm_s32le_planar
+ --enable-decoder=pcm_s64be
+ --enable-decoder=pcm_s64le
+ --enable-decoder=pcm_s8
+ --enable-decoder=pcm_s8_planar
+ --enable-decoder=pcm_u16be
+ --enable-decoder=pcm_u16le'
+
+#filters
+FFMPEGCONF+='
+ --enable-filter=scale
+ --enable-filter=aresample
+ --enable-filter=aformat
+ --enable-filter=rotate
+ --enable-filter=format
+ --enable-filter=drawtext'
+
+if [ "$1" == "uwp" ]; then
+ EXTRACFLAGS='-MD -DWINAPI_FAMILY=WINAPI_FAMILY_APP -D_WIN32_WINNT=0x0A00 -I../../../../../msvc/include -I../../../../../msvc/include/opus'
+ if [ "$2" == "x64" ]; then
+ echo "configure and make ffmpeg for UWP-x64..."
+ EXTRALDFLAGS='-APPCONTAINER WindowsApp.lib libopus.lib libx264.lib -LIBPATH:../../../../../msvc/lib/x64'
+ FFMPEGCONF+=' --arch=x86_64'
+ PREFIX=../../../Build/Windows10/x64
+ OUTDIR=Output/Windows10/x64
+ elif [ "$2" == "x86" ]; then
+ echo "configure and make ffmpeg for UWP-x86..."
+ EXTRALDFLAGS='-APPCONTAINER WindowsApp.lib libopus.lib libx264.lib -LIBPATH:../../../../../msvc/lib/x86'
+ FFMPEGCONF+=' --arch=x86'
+ PREFIX=../../../Build/Windows10/x86
+ OUTDIR=Output/Windows10/x86
+ fi
+elif [ "$1" == "win32" ]; then
+ EXTRACFLAGS='-MD -D_WINDLL -I../../../../../msvc/include -I../../../../../msvc/include/opus -I../../../../../msvc/include/vpx -I../../../../../msvc/include/ffnvcodec -I../../../../../msvc/include/mfx -I../../../../../msvc/include/lame'
+ FFMPEGCONF+='
+ --enable-libvpx
+ --enable-encoder=libvpx_vp8
+ --enable-decoder=vp8
+ --enable-decoder=vp9'
+ FFMPEGCONF+='
+ --enable-indev=dshow
+ --enable-indev=gdigrab
+ --enable-dxva2'
+ FFMPEGCONF+='
+ --enable-ffnvcodec
+ --enable-cuvid
+ --enable-nvdec
+ --enable-nvenc
+ --enable-hwaccel=h264_nvdec
+ --enable-hwaccel=hevc_nvdec
+ --enable-hwaccel=vp8_nvdec
+ --enable-hwaccel=mjpeg_nvdec
+ --enable-encoder=h264_nvenc
+ --enable-encoder=hevc_nvenc'
+ FFMPEGCONF+='
+ --enable-libmfx
+ --enable-encoder=h264_qsv
+ --enable-encoder=hevc_qsv
+ --enable-encoder=mjpeg_qsv
+ --enable-decoder=vp8_qsv
+ --enable-decoder=h264_qsv
+ --enable-decoder=hevc_qsv
+ --enable-decoder=mjpeg_qsv
+ --enable-decoder=vp9_qsv
+ --enable-filter=scale_qsv
+ --enable-filter=overlay_qsv'
+ if [ "$2" == "x64" ]; then
+ echo "configure and make ffmpeg for win32-x64..."
+ EXTRALDFLAGS='-APPCONTAINER:NO -MACHINE:x64 Ole32.lib Kernel32.lib Gdi32.lib User32.lib Strmiids.lib Advapi32.lib OleAut32.lib Shlwapi.lib Vfw32.lib Secur32.lib Advapi32.lib libopus.lib libx264.lib libvpx.lib libmfx.lib -LIBPATH:../../../../../msvc/lib/x64'
+ FFMPEGCONF+=' --arch=x86_64'
+ PREFIX=../../../Build/win32/x64
+ OUTDIR=Output/win32/x64
+ elif [ "$2" == "x86" ]; then
+ echo "configure and make ffmpeg for win32-x86..."
+ EXTRALDFLAGS='-APPCONTAINER:NO -MACHINE:x86 Ole32.lib Kernel32.lib Gdi32.lib User32.lib Strmiids.lib OleAut32.lib Shlwapi.lib Vfw32.lib Secur32.lib Advapi32.lib libopus.lib libx264.lib libvpx.lib libmfx.lib -LIBPATH:../../../../../msvc/lib/x86'
+ FFMPEGCONF+=' --arch=x86'
+ PREFIX=../../../Build/win32/x86
+ OUTDIR=Output/win32/x86
+ fi
+fi
+rm -rf $OUTDIR
+mkdir -p $OUTDIR
+cd $OUTDIR
+pwd
+FFMPEGCONF=$(echo $FFMPEGCONF | sed -e "s/[[:space:]]\+/ /g")
+set -x
+set -e
+../../../configure $FFMPEGCONF --extra-cflags="${EXTRACFLAGS}" --extra-ldflags="${EXTRALDFLAGS}" --prefix="${PREFIX}"
+make -j8 install
+cd ../../..
diff --git a/WhisperTranscript/gb0.wav b/WhisperTranscript/gb0.wav
new file mode 100644
index 0000000..94455b4
--- /dev/null
+++ b/WhisperTranscript/gb0.wav
Binary files differ
diff --git a/WhisperTranscript/getonnxio.py b/WhisperTranscript/getonnxio.py
new file mode 100644
index 0000000..7385a51
--- /dev/null
+++ b/WhisperTranscript/getonnxio.py
@@ -0,0 +1,83 @@
+import onnx
+
+model = onnx.load('data/assets/mModelEncoder.onnx')
+output =[node.name for node in model.graph.output]
+
+input_all = [node.name for node in model.graph.input]
+input_initializer = [node.name for node in model.graph.initializer]
+net_feed_input = list(set(input_all) - set(input_initializer))
+
+print('Encoder Inputs: ', net_feed_input)
+print('Encoder Outputs: ', output)
+print("")
+
+onnx.checker.check_model(model)
+graph_def = model.graph
+
+inputs = graph_def.input
+for graph_input in inputs:
+ input_shape = []
+ for d in graph_input.type.tensor_type.shape.dim:
+ if d.dim_value == 0:
+ input_shape.append(None)
+ else:
+ input_shape.append(d.dim_value)
+ print(
+ f"Input Name: {graph_input.name}, Input Data Type: {graph_input.type.tensor_type.elem_type}, Input Shape: {input_shape}"
+ )
+
+
+print("")
+outputs = graph_def.output
+for graph_output in outputs:
+ output_shape = []
+ for d in graph_output.type.tensor_type.shape.dim:
+ if d.dim_value == 0:
+ output_shape.append(None)
+ else:
+ output_shape.append(d.dim_value)
+ print(
+ f"Output Name: {graph_output.name}, Output Data Type: {graph_output.type.tensor_type.elem_type}, Output Shape: {output_shape}"
+ )
+
+
+model = onnx.load('data/assets/mModelDecoder.onnx')
+output =[node.name for node in model.graph.output]
+
+input_all = [node.name for node in model.graph.input]
+input_initializer = [node.name for node in model.graph.initializer]
+net_feed_input = list(set(input_all) - set(input_initializer))
+
+print("\n")
+
+print('Decoder Inputs: ', net_feed_input)
+print('Decoder Outputs: ', output)
+print("")
+
+onnx.checker.check_model(model)
+graph_def = model.graph
+
+inputs = graph_def.input
+for graph_input in inputs:
+ input_shape = []
+ for d in graph_input.type.tensor_type.shape.dim:
+ if d.dim_value == 0:
+ input_shape.append(None)
+ else:
+ input_shape.append(d.dim_value)
+ print(
+ f"Input Name: {graph_input.name}, Input Data Type: {graph_input.type.tensor_type.elem_type}, Input Shape: {input_shape}"
+ )
+
+print("")
+outputs = graph_def.output
+for graph_output in outputs:
+ output_shape = []
+ for d in graph_output.type.tensor_type.shape.dim:
+ if d.dim_value == 0:
+ output_shape.append(None)
+ else:
+ output_shape.append(d.dim_value)
+ print(
+ f"Output Name: {graph_output.name}, Output Data Type: {graph_output.type.tensor_type.elem_type}, Output Shape: {output_shape}"
+ )
diff --git a/WhisperTranscript/jami.wav b/WhisperTranscript/jami.wav
new file mode 100644
index 0000000..48cb5cb
--- /dev/null
+++ b/WhisperTranscript/jami.wav
Binary files differ
diff --git a/WhisperTranscript/jfk.wav b/WhisperTranscript/jfk.wav
new file mode 100644
index 0000000..3184d37
--- /dev/null
+++ b/WhisperTranscript/jfk.wav
Binary files differ
diff --git a/WhisperTranscript/main.cpp b/WhisperTranscript/main.cpp
new file mode 100644
index 0000000..00c976d
--- /dev/null
+++ b/WhisperTranscript/main.cpp
@@ -0,0 +1,166 @@
+/**
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <iostream>
+#include <string.h>
+#include <thread>
+#include <memory>
+#include <plugin/jamiplugin.h>
+
+#include "TranscriptMediaHandler.h"
+#include "PluginPreferenceHandler.h"
+
+#ifdef __DEBUG__
+#include <common.h>
+#include <assert.h>
+#include <yaml-cpp/yaml.h>
+#include <fstream>
+#include <AVFrameIO.h>
+#endif
+
+#ifdef WIN32
+#define EXPORT_PLUGIN __declspec(dllexport)
+#else
+#define EXPORT_PLUGIN
+#endif
+
+#define WhisperTranscript_VERSION_MAJOR 0
+#define WhisperTranscript_VERSION_MINOR 0
+#define WhisperTranscript_VERSION_PATCH 0
+
+extern "C" {
+
+void
+pluginExit(void)
+{}
+
+EXPORT_PLUGIN JAMI_PluginExitFunc
+JAMI_dynPluginInit(const JAMI_PluginAPI* api)
+{
+ std::cout << "**************************" << std::endl;
+ std::cout << "** WhisperTranscript **" << std::endl;
+ std::cout << "**************************" << std::endl << std::endl;
+ std::cout << "Version " << WhisperTranscript_VERSION_MAJOR << "." << WhisperTranscript_VERSION_MINOR << "."
+ << WhisperTranscript_VERSION_PATCH << std::endl;
+
+ // If invokeService doesn't return an error
+ if (api) {
+ if (api->version.api < JAMI_PLUGIN_API_VERSION)
+ return nullptr;
+
+ std::map<std::string, std::map<std::string, std::string>> preferences;
+ api->invokeService(api, "getPluginAccPreferences", &preferences);
+ std::string dataPath;
+ api->invokeService(api, "getPluginDataPath", &dataPath);
+
+ auto fmpPluginPreferenceHandler
+ = std::make_unique<jami::PluginPreferenceHandler>(api,
+ std::move(preferences),
+ dataPath);
+
+ auto fmpTranscriptMediaHandler
+ = std::make_unique<jami::TranscriptMediaHandler>(std::move(dataPath),
+ fmpPluginPreferenceHandler.get());
+
+ fmpPluginPreferenceHandler->setTranscriptHandler(fmpTranscriptMediaHandler.get());
+
+ if (api->manageComponent(api,
+ "CallMediaHandlerManager",
+ fmpTranscriptMediaHandler.release())) {
+ return nullptr;
+ }
+ if (api->manageComponent(api,
+ "PreferenceHandlerManager",
+ fmpPluginPreferenceHandler.release())) {
+ return nullptr;
+ }
+ }
+ return pluginExit;
+}
+}
+
+#ifdef __DEBUG__
+
+int
+main ()
+{
+ std::cout << "***************************************" << std::endl;
+ std::cout << "** WhisperTranscript Debug Version **" << std::endl;
+ std::cout << "***************************************" << std::endl;
+ std::cout << "Version " << WhisperTranscript_VERSION_MAJOR << "." << WhisperTranscript_VERSION_MINOR << "."
+ << WhisperTranscript_VERSION_PATCH << std::endl;
+
+ std::ifstream file;
+ file_utils::openStream(file, "testPreferences.yml");
+
+ assert(file.is_open());
+ YAML::Node node = YAML::Load(file);
+
+ assert(node.IsMap());
+ std::map<std::string, std::map<std::string, std::string>> preferences;
+ preferences["default"] = {};
+ for (const auto& kv : node) {
+ preferences["default"][kv.first.as<std::string>()] = kv.second.as<std::string>();
+ std::cout << "Key: " << kv.first.as<std::string>() << "; Value: " << kv.second.as<std::string>() << std::endl;
+ }
+
+#ifdef _WIN32
+ std::string dataPath = "../data";
+#else
+ std::string dataPath = "data";
+#endif
+
+ auto fmpPluginPreferenceHandler
+ = std::make_unique<jami::PluginPreferenceHandler>(nullptr, std::move(preferences), dataPath);
+ auto fmpTranscriptMediaHandler
+ = std::make_unique<jami::TranscriptMediaHandler>(std::move(dataPath),
+ fmpPluginPreferenceHandler.get());
+ fmpPluginPreferenceHandler->setTranscriptHandler(fmpTranscriptMediaHandler.get());
+
+ auto subject = std::make_shared<jami::PublishObservable<AVFrame*>>();
+
+ // Valid Read frames from audio sample file and send to subscriber
+ fmpTranscriptMediaHandler->notifyAVFrameSubject(StreamData("testCall",
+ true,
+ StreamType::audio,
+ "origin",
+ "destiny"),
+ subject);
+ av_utils::readAndNotifyAVFrame(preferences["default"]["audiosample"],
+ subject.get(),
+ preferences["default"]["audiooutput"],
+ AVMEDIA_TYPE_AUDIO);
+
+ // Valid Read frames from video sample file and send to subscriber
+ fmpTranscriptMediaHandler->notifyAVFrameSubject(StreamData("testCall",
+ true,
+ StreamType::video,
+ "origin",
+ "destiny"),
+ subject);
+ av_utils::readAndNotifyAVFrame(preferences["default"]["videosample"],
+ subject.get(),
+ preferences["default"]["videooutput"],
+ AVMEDIA_TYPE_VIDEO);
+
+ return 0;
+}
+
+#endif
diff --git a/WhisperTranscript/manifest.json b/WhisperTranscript/manifest.json
new file mode 100644
index 0000000..ae1e2b6
--- /dev/null
+++ b/WhisperTranscript/manifest.json
@@ -0,0 +1,5 @@
+{
+ "name": "WhisperTranscript",
+ "description": "Transcribe your calls if they are recorded",
+ "version": "0.0.0"
+}
\ No newline at end of file
diff --git a/WhisperTranscript/modelSRC/mLogSoftMax.onnx b/WhisperTranscript/modelSRC/mLogSoftMax.onnx
new file mode 100644
index 0000000..2f90b73
--- /dev/null
+++ b/WhisperTranscript/modelSRC/mLogSoftMax.onnx
Binary files differ
diff --git a/WhisperTranscript/modelSRC/mModelDecoder.onnx b/WhisperTranscript/modelSRC/mModelDecoder.onnx
new file mode 100644
index 0000000..323114d
--- /dev/null
+++ b/WhisperTranscript/modelSRC/mModelDecoder.onnx
Binary files differ
diff --git a/WhisperTranscript/modelSRC/mModelDecoder.ort b/WhisperTranscript/modelSRC/mModelDecoder.ort
new file mode 100644
index 0000000..dca38b7
--- /dev/null
+++ b/WhisperTranscript/modelSRC/mModelDecoder.ort
Binary files differ
diff --git a/WhisperTranscript/modelSRC/mModelEncoder.onnx b/WhisperTranscript/modelSRC/mModelEncoder.onnx
new file mode 100644
index 0000000..5da3279
--- /dev/null
+++ b/WhisperTranscript/modelSRC/mModelEncoder.onnx
Binary files differ
diff --git a/WhisperTranscript/modelSRC/mModelEncoder.ort b/WhisperTranscript/modelSRC/mModelEncoder.ort
new file mode 100644
index 0000000..abc7d9b
--- /dev/null
+++ b/WhisperTranscript/modelSRC/mModelEncoder.ort
Binary files differ
diff --git a/WhisperTranscript/package.json b/WhisperTranscript/package.json
new file mode 100644
index 0000000..72acbc7
--- /dev/null
+++ b/WhisperTranscript/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "WhisperTranscript",
+ "version": "0.0.0",
+ "extractLibs": false,
+ "deps": [
+ "fmt"
+ ],
+ "defines": [
+ "NVIDIA=False",
+ "TESTPROCESS=False"
+ ],
+ "custom_scripts": {
+ "pre_build": [
+ "mkdir msvc"
+ ],
+ "build": [
+ "cmake --build ./msvc --config Release"
+ ],
+ "post_build": []
+ }
+}
\ No newline at end of file
diff --git a/WhisperTranscript/sample.mp4 b/WhisperTranscript/sample.mp4
new file mode 100644
index 0000000..f71fcb8
--- /dev/null
+++ b/WhisperTranscript/sample.mp4
Binary files differ
diff --git a/WhisperTranscript/testPreferences.yml b/WhisperTranscript/testPreferences.yml
new file mode 100644
index 0000000..eeb3a6c
--- /dev/null
+++ b/WhisperTranscript/testPreferences.yml
@@ -0,0 +1,9 @@
+avstream: "in"
+audiosample: "jami.wav"
+videosample: "sample.mp4"
+audiooutput: ""
+videooutput: "processed.mp4"
+subtitle: " "
+background: "black@0.0"
+position: "2"
+fontsize: "36"
\ No newline at end of file
diff --git a/WhisperTranscript/zlib/libzlib.vcxproj b/WhisperTranscript/zlib/libzlib.vcxproj
new file mode 100644
index 0000000..81f9634
--- /dev/null
+++ b/WhisperTranscript/zlib/libzlib.vcxproj
@@ -0,0 +1,918 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="DebugDLL|Win32">
+ <Configuration>DebugDLL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DebugDLL|x64">
+ <Configuration>DebugDLL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="ReleaseDLL|Win32">
+ <Configuration>ReleaseDLL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="ReleaseDLL|x64">
+ <Configuration>ReleaseDLL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="ReleaseLTO|Win32">
+ <Configuration>ReleaseLTO</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="ReleaseLTO|x64">
+ <Configuration>ReleaseLTO</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}</ProjectGuid>
+ <RootNamespace>libzlib</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugDLL|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugDLL|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTO|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTO|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings" />
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugDLL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugDLL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTO|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTO|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
+ <IntDir>$(SolutionDir)obj\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+ <TargetName>libzlibd</TargetName>
+ <CustomBuildAfterTargets>Clean</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
+ <IntDir>$(SolutionDir)obj\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+ <TargetName>libzlib</TargetName>
+ <CustomBuildAfterTargets>Clean</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTO|Win32'">
+ <OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
+ <IntDir>$(SolutionDir)obj\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+ <TargetName>libzlib</TargetName>
+ <CustomBuildAfterTargets>Clean</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|Win32'">
+ <OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
+ <IntDir>$(SolutionDir)obj\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+ <TargetName>zlib</TargetName>
+ <CustomBuildAfterTargets>Clean</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugDLL|Win32'">
+ <OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
+ <IntDir>$(SolutionDir)obj\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+ <TargetName>zlibd</TargetName>
+ <CustomBuildAfterTargets>Clean</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
+ <IntDir>$(SolutionDir)obj\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+ <TargetName>libzlibd</TargetName>
+ <CustomBuildAfterTargets>Clean</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
+ <IntDir>$(SolutionDir)obj\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+ <TargetName>libzlib</TargetName>
+ <CustomBuildAfterTargets>Clean</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTO|x64'">
+ <OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
+ <IntDir>$(SolutionDir)obj\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+ <TargetName>libzlib</TargetName>
+ <CustomBuildAfterTargets>Clean</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|x64'">
+ <OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
+ <IntDir>$(SolutionDir)obj\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+ <TargetName>zlib</TargetName>
+ <CustomBuildAfterTargets>Clean</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugDLL|x64'">
+ <OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
+ <IntDir>$(SolutionDir)obj\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+ <TargetName>zlibd</TargetName>
+ <CustomBuildAfterTargets>Clean</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0502;_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <AdditionalIncludeDirectories>.\;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ProgramDataBaseFileName>$(OutDir)\lib\x86\$(TargetName).pdb</ProgramDataBaseFileName>
+ <MinimalRebuild>false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ <Lib>
+ <OutputFile>$(OutDir)\lib\x86\$(TargetName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Lib>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ <Lib>
+ <SubSystem>Windows</SubSystem>
+ </Lib>
+ <MASM>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ </MASM>
+ <PostBuildEvent>
+ <Command>mkdir "$(OutDir)"\include
+copy ..\zlib.h "$(OutDir)"\include
+copy "$(OutDir)"\..\src\zlib\zconf.h "$(OutDir)"\include /Y
+copy "$(OutDir)"\lib\$(Platform)\libzlib.lib "$(OutDir)"\lib\$(Platform)\zlib.lib /Y
+mkdir $(OutDir)\licenses
+copy ..\README $(OutDir)\licenses\zlib.txt</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>if exist ..\zconf.h (
+del ..\zconf.h
+)
+if exist "$(OutDir)"\include\zlib.h (
+del "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del "$(OutDir)"\include\zconf.h
+)</Command>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Message>Custom Clean Step</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>force_clean</Outputs>
+ <Command>if exist "$(OutDir)"\include\zlib.h (
+del /f /q "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del /f /q "$(OutDir)"\include\zconf.h
+)
+if exist $(OutDir)\licenses\zlib.txt (
+del /f /q $(OutDir)\licenses\zlib.txt
+)</Command>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN64;_WIN32_WINNT=0x0600;_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <AdditionalIncludeDirectories>.\;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ProgramDataBaseFileName>$(OutDir)\lib\x64\$(TargetName).pdb</ProgramDataBaseFileName>
+ <MinimalRebuild>false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ <Lib>
+ <SubSystem>Windows</SubSystem>
+ <OutputFile>$(OutDir)\lib\x64\$(TargetName)$(TargetExt)</OutputFile>
+ </Lib>
+ <MASM>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ </MASM>
+ <PostBuildEvent>
+ <Command>mkdir "$(OutDir)"\include
+copy ..\zlib.h "$(OutDir)"\include
+copy "$(OutDir)"\..\src\zlib\zconf.h "$(OutDir)"\include /Y
+copy "$(OutDir)"\lib\$(Platform)\libzlib.lib "$(OutDir)"\lib\$(Platform)\zlib.lib /Y
+mkdir $(OutDir)\licenses
+copy ..\README $(OutDir)\licenses\zlib.txt</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>if exist ..\zconf.h (
+del ..\zconf.h
+)
+if exist "$(OutDir)"\include\zlib.h (
+del "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del "$(OutDir)"\include\zconf.h
+)</Command>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Message>Custom Clean Step</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>force_clean</Outputs>
+ <Command>if exist "$(OutDir)"\include\zlib.h (
+del /f /q "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del /f /q "$(OutDir)"\include\zconf.h
+)
+if exist $(OutDir)\licenses\zlib.txt (
+del /f /q $(OutDir)\licenses\zlib.txt
+)</Command>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugDLL|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0502;_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <AdditionalIncludeDirectories>.\;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <MinimalRebuild>false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <ImportLibrary>$(OutDir)\lib\x86\$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <ProfileGuidedDatabase>$(IntDir)\$(TargetName).pgd</ProfileGuidedDatabase>
+ <ProgramDatabaseFile>$(OutDir)\lib\x86\$(TargetName).pdb</ProgramDatabaseFile>
+ <OutputFile>$(OutDir)\bin\x86\$(TargetName)$(TargetExt)</OutputFile>
+ <ModuleDefinitionFile>..\contrib\vstudio\vc11\zlibvc.def</ModuleDefinitionFile>
+ <LargeAddressAware>true</LargeAddressAware>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <MinimumRequiredVersion>5.1</MinimumRequiredVersion>
+ </Link>
+ <MASM>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ </MASM>
+ <PostBuildEvent>
+ <Command>mkdir "$(OutDir)"\include
+copy ..\zlib.h "$(OutDir)"\include
+copy "$(OutDir)"\..\src\zlib\zconf.h "$(OutDir)"\include /Y
+copy "$(OutDir)"\lib\$(Platform)\libzlib.lib "$(OutDir)"\lib\$(Platform)\zlib.lib /Y
+mkdir $(OutDir)\licenses
+copy ..\README $(OutDir)\licenses\zlib.txt</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>if exist ..\zconf.h (
+del ..\zconf.h
+)
+if exist "$(OutDir)"\include\zlib.h (
+del "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del "$(OutDir)"\include\zconf.h
+)</Command>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Message>Custom Clean Step</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>force_clean</Outputs>
+ <Command>if exist "$(OutDir)"\include\zlib.h (
+del /f /q "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del /f /q "$(OutDir)"\include\zconf.h
+)
+if exist $(OutDir)\licenses\zlib.txt (
+del /f /q $(OutDir)\licenses\zlib.txt
+)</Command>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugDLL|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN64;_WIN32_WINNT=0x0600;_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <AdditionalIncludeDirectories>.\;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <MinimalRebuild>false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)\bin\x64\$(TargetName)$(TargetExt)</OutputFile>
+ <ProgramDatabaseFile>$(OutDir)\lib\x64\$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <ProfileGuidedDatabase>$(IntDir)\$(TargetName).pgd</ProfileGuidedDatabase>
+ <ImportLibrary>$(OutDir)\lib\x64\$(TargetName).lib</ImportLibrary>
+ <ModuleDefinitionFile>..\contrib\vstudio\vc11\zlibvc.def</ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <MinimumRequiredVersion>6.0</MinimumRequiredVersion>
+ </Link>
+ <MASM>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ </MASM>
+ <PostBuildEvent>
+ <Command>mkdir "$(OutDir)"\include
+copy ..\zlib.h "$(OutDir)"\include
+copy "$(OutDir)"\..\src\zlib\zconf.h "$(OutDir)"\include /Y
+copy "$(OutDir)"\lib\$(Platform)\libzlib.lib "$(OutDir)"\lib\$(Platform)\zlib.lib /Y
+mkdir $(OutDir)\licenses
+copy ..\README $(OutDir)\licenses\zlib.txt</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>if exist ..\zconf.h (
+del ..\zconf.h
+)
+if exist "$(OutDir)"\include\zlib.h (
+del "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del "$(OutDir)"\include\zconf.h
+)</Command>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Message>Custom Clean Step</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>force_clean</Outputs>
+ <Command>if exist "$(OutDir)"\include\zlib.h (
+del /f /q "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del /f /q "$(OutDir)"\include\zconf.h
+)
+if exist $(OutDir)\licenses\zlib.txt (
+del /f /q $(OutDir)\licenses\zlib.txt
+)</Command>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+ <StringPooling>true</StringPooling>
+ <AdditionalIncludeDirectories>.\;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <InterproceduralOptimization>SingleFile</InterproceduralOptimization>
+ <ProgramDataBaseFileName>$(OutDir)\lib\x86\$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ <Lib>
+ <OutputFile>$(OutDir)\lib\x86\$(TargetName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Lib>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ <Lib>
+ <SubSystem>Windows</SubSystem>
+ </Lib>
+ <MASM>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ </MASM>
+ <PostBuildEvent>
+ <Command>mkdir "$(OutDir)"\include
+copy ..\zlib.h "$(OutDir)"\include
+copy "$(OutDir)"\..\src\zlib\zconf.h "$(OutDir)"\include /Y
+copy "$(OutDir)"\lib\$(Platform)\libzlib.lib "$(OutDir)"\lib\$(Platform)\zlib.lib /Y
+mkdir $(OutDir)\licenses
+copy ..\README $(OutDir)\licenses\zlib.txt</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>if exist ..\zconf.h (
+del ..\zconf.h
+)
+if exist "$(OutDir)"\include\zlib.h (
+del "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del "$(OutDir)"\include\zconf.h
+)</Command>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Message>Custom Clean Step</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>force_clean</Outputs>
+ <Command>if exist "$(OutDir)"\include\zlib.h (
+del /f /q "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del /f /q "$(OutDir)"\include\zconf.h
+)
+if exist $(OutDir)\licenses\zlib.txt (
+del /f /q $(OutDir)\licenses\zlib.txt
+)</Command>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTO|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+ <StringPooling>true</StringPooling>
+ <AdditionalIncludeDirectories>.\;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <InterproceduralOptimization>SingleFile</InterproceduralOptimization>
+ <ProgramDataBaseFileName>$(OutDir)\lib\x86\$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ <Lib>
+ <OutputFile>$(OutDir)\lib\x86\$(TargetName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Lib>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ <Lib>
+ <SubSystem>Windows</SubSystem>
+ </Lib>
+ <MASM>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ </MASM>
+ <PostBuildEvent>
+ <Command>mkdir "$(OutDir)"\include
+copy ..\zlib.h "$(OutDir)"\include
+copy "$(OutDir)"\..\src\zlib\zconf.h "$(OutDir)"\include /Y
+copy "$(OutDir)"\lib\$(Platform)\libzlib.lib "$(OutDir)"\lib\$(Platform)\zlib.lib /Y
+mkdir $(OutDir)\licenses
+copy ..\README $(OutDir)\licenses\zlib.txt</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>if exist ..\zconf.h (
+del ..\zconf.h
+)
+if exist "$(OutDir)"\include\zlib.h (
+del "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del "$(OutDir)"\include\zconf.h
+)</Command>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Message>Custom Clean Step</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>force_clean</Outputs>
+ <Command>if exist "$(OutDir)"\include\zlib.h (
+del /f /q "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del /f /q "$(OutDir)"\include\zconf.h
+)
+if exist $(OutDir)\licenses\zlib.txt (
+del /f /q $(OutDir)\licenses\zlib.txt
+)</Command>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN64;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+ <StringPooling>true</StringPooling>
+ <AdditionalIncludeDirectories>.\;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <InterproceduralOptimization>SingleFile</InterproceduralOptimization>
+ <ProgramDataBaseFileName>$(OutDir)\lib\x64\$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ <Lib>
+ <SubSystem>Windows</SubSystem>
+ <OutputFile>$(OutDir)\lib\x64\$(TargetName)$(TargetExt)</OutputFile>
+ </Lib>
+ <MASM>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ </MASM>
+ <PostBuildEvent>
+ <Command>mkdir "$(OutDir)"\include
+copy ..\zlib.h "$(OutDir)"\include
+copy "$(OutDir)"\..\src\zlib\zconf.h "$(OutDir)"\include /Y
+copy "$(OutDir)"\lib\$(Platform)\libzlib.lib "$(OutDir)"\lib\$(Platform)\zlib.lib /Y
+mkdir $(OutDir)\licenses
+copy ..\README $(OutDir)\licenses\zlib.txt</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>if exist ..\zconf.h (
+del ..\zconf.h
+)
+if exist "$(OutDir)"\include\zlib.h (
+del "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del "$(OutDir)"\include\zconf.h
+)</Command>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Message>Custom Clean Step</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>force_clean</Outputs>
+ <Command>if exist "$(OutDir)"\include\zlib.h (
+del /f /q "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del /f /q "$(OutDir)"\include\zconf.h
+)
+if exist $(OutDir)\licenses\zlib.txt (
+del /f /q $(OutDir)\licenses\zlib.txt
+)</Command>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTO|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN64;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+ <StringPooling>true</StringPooling>
+ <AdditionalIncludeDirectories>.\;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <InterproceduralOptimization>SingleFile</InterproceduralOptimization>
+ <ProgramDataBaseFileName>$(OutDir)\lib\x64\$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ <Lib>
+ <SubSystem>Windows</SubSystem>
+ <OutputFile>$(OutDir)\lib\x64\$(TargetName)$(TargetExt)</OutputFile>
+ </Lib>
+ <MASM>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ </MASM>
+ <PostBuildEvent>
+ <Command>mkdir "$(OutDir)"\include
+copy ..\zlib.h "$(OutDir)"\include
+copy "$(OutDir)"\..\src\zlib\zconf.h "$(OutDir)"\include /Y
+copy "$(OutDir)"\lib\$(Platform)\libzlib.lib "$(OutDir)"\lib\$(Platform)\zlib.lib /Y
+mkdir $(OutDir)\licenses
+copy ..\README $(OutDir)\licenses\zlib.txt</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>if exist ..\zconf.h (
+del ..\zconf.h
+)
+if exist "$(OutDir)"\include\zlib.h (
+del "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del "$(OutDir)"\include\zconf.h
+)</Command>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Message>Custom Clean Step</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>force_clean</Outputs>
+ <Command>if exist "$(OutDir)"\include\zlib.h (
+del /f /q "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del /f /q "$(OutDir)"\include\zconf.h
+)
+if exist $(OutDir)\licenses\zlib.txt (
+del /f /q $(OutDir)\licenses\zlib.txt
+)</Command>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+ <StringPooling>true</StringPooling>
+ <AdditionalIncludeDirectories>.\;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <ImportLibrary>$(OutDir)\lib\x86\$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <ProfileGuidedDatabase>$(IntDir)\$(TargetName).pgd</ProfileGuidedDatabase>
+ <ProgramDatabaseFile>$(OutDir)\lib\x86\$(TargetName).pdb</ProgramDatabaseFile>
+ <OutputFile>$(OutDir)\bin\x86\$(TargetName)$(TargetExt)</OutputFile>
+ <ModuleDefinitionFile>..\contrib\vstudio\vc11\zlibvc.def</ModuleDefinitionFile>
+ <LargeAddressAware>true</LargeAddressAware>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <MinimumRequiredVersion>5.1</MinimumRequiredVersion>
+ </Link>
+ <MASM>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ </MASM>
+ <PostBuildEvent>
+ <Command>mkdir "$(OutDir)"\include
+copy ..\zlib.h "$(OutDir)"\include
+copy "$(OutDir)"\..\src\zlib\zconf.h "$(OutDir)"\include /Y
+copy "$(OutDir)"\lib\$(Platform)\libzlib.lib "$(OutDir)"\lib\$(Platform)\zlib.lib /Y
+mkdir $(OutDir)\licenses
+copy ..\README $(OutDir)\licenses\zlib.txt</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>if exist ..\zconf.h (
+del ..\zconf.h
+)
+if exist "$(OutDir)"\include\zlib.h (
+del "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del "$(OutDir)"\include\zconf.h
+)</Command>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Message>Custom Clean Step</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>force_clean</Outputs>
+ <Command>if exist "$(OutDir)"\include\zlib.h (
+del /f /q "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del /f /q "$(OutDir)"\include\zconf.h
+)
+if exist $(OutDir)\licenses\zlib.txt (
+del /f /q $(OutDir)\licenses\zlib.txt
+)</Command>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN64;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+ <StringPooling>true</StringPooling>
+ <AdditionalIncludeDirectories>.\;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>$(OutDir)\bin\x64\$(TargetName)$(TargetExt)</OutputFile>
+ <ProgramDatabaseFile>$(OutDir)\lib\x64\$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <ProfileGuidedDatabase>$(IntDir)\$(TargetName).pgd</ProfileGuidedDatabase>
+ <ImportLibrary>$(OutDir)\lib\x64\$(TargetName).lib</ImportLibrary>
+ <ModuleDefinitionFile>..\contrib\vstudio\vc11\zlibvc.def</ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <MinimumRequiredVersion>6.0</MinimumRequiredVersion>
+ </Link>
+ <MASM>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ </MASM>
+ <PostBuildEvent>
+ <Command>mkdir "$(OutDir)"\include
+copy ..\zlib.h "$(OutDir)"\include
+copy "$(OutDir)"\..\src\zlib\zconf.h "$(OutDir)"\include /Y
+copy "$(OutDir)"\lib\$(Platform)\libzlib.lib "$(OutDir)"\lib\$(Platform)\zlib.lib /Y
+mkdir $(OutDir)\licenses
+copy ..\README $(OutDir)\licenses\zlib.txt</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>if exist ..\zconf.h (
+del ..\zconf.h
+)
+if exist "$(OutDir)"\include\zlib.h (
+del "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del "$(OutDir)"\include\zconf.h
+)</Command>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Message>Custom Clean Step</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>force_clean</Outputs>
+ <Command>if exist "$(OutDir)"\include\zlib.h (
+del /f /q "$(OutDir)"\include\zlib.h
+)
+if exist "$(OutDir)"\include\zconf.h (
+del /f /q "$(OutDir)"\include\zconf.h
+)
+if exist $(OutDir)\licenses\zlib.txt (
+del /f /q $(OutDir)\licenses\zlib.txt
+)</Command>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\adler32.c" />
+ <ClCompile Include="..\compress.c" />
+ <ClCompile Include="..\crc32.c" />
+ <ClCompile Include="..\deflate.c" />
+ <ClCompile Include="..\gzclose.c" />
+ <ClCompile Include="..\gzlib.c" />
+ <ClCompile Include="..\gzread.c" />
+ <ClCompile Include="..\gzwrite.c" />
+ <ClCompile Include="..\infback.c" />
+ <ClCompile Include="..\inffast.c" />
+ <ClCompile Include="..\inflate.c" />
+ <ClCompile Include="..\inftrees.c" />
+ <ClCompile Include="..\trees.c" />
+ <ClCompile Include="..\uncompr.c" />
+ <ClCompile Include="..\zutil.c" />
+ <ClCompile Include="..\contrib\minizip\ioapi.c" />
+ <ClCompile Include="..\contrib\minizip\iowin32.c">
+ <ExcludedFromBuild Condition="'$(Configuration)'=='Debug'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)'=='Release'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)'=='ReleaseLTO'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="..\contrib\minizip\unzip.c" />
+ <ClCompile Include="..\contrib\minizip\zip.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\crc32.h" />
+ <ClInclude Include="..\deflate.h" />
+ <ClInclude Include="..\inffast.h" />
+ <ClInclude Include="..\inffixed.h" />
+ <ClInclude Include="..\inflate.h" />
+ <ClInclude Include="..\inftrees.h" />
+ <ClInclude Include="..\trees.h" />
+ <ClInclude Include="..\zlib.h" />
+ <ClInclude Include="..\zutil.h" />
+ <ClInclude Include="..\contrib\minizip\ioapi.h" />
+ <ClInclude Include="..\contrib\minizip\unzip.h" />
+ <ClInclude Include="..\contrib\minizip\zip.h" />
+ <ClInclude Include="zconf.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\contrib\vstudio\vc11\zlib.rc">
+ <ExcludedFromBuild Condition="'$(Configuration)'=='Debug'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)'=='Release'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)'=='ReleaseLTO'">true</ExcludedFromBuild>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\contrib\vstudio\vc11\zlibvc.def" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets" />
+</Project>
diff --git a/WhisperTranscript/zlib/package.json b/WhisperTranscript/zlib/package.json
new file mode 100644
index 0000000..fdfec5e
--- /dev/null
+++ b/WhisperTranscript/zlib/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "zlib",
+ "version": "8e4e3ead55cdd296130242d86b44b92fde3ea4d4",
+ "url": "https://github.com/ShiftMediaProject/zlib/archive/__VERSION__.tar.gz",
+ "deps": [],
+ "patches": [],
+ "win_patches": [],
+ "project_paths": [
+ "SMP/libzlib.vcxproj"
+ ],
+ "with_env" : "",
+ "custom_scripts": {
+ "pre_build": ["copy %cd%\\\\..\\\\..\\\\src\\\\zlib\\\\libzlib.vcxproj %cd%\\\\SMP\\\\libzlib.vcxproj /Y"],
+ "build": [],
+ "post_build": []
+ }
+}
diff --git a/WhisperTranscript/zlib/zconf.h b/WhisperTranscript/zlib/zconf.h
new file mode 100644
index 0000000..df47fef
--- /dev/null
+++ b/WhisperTranscript/zlib/zconf.h
@@ -0,0 +1,519 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
+#define Z_PREFIX_SET
+
+/* all linked symbols and init macros */
+#define _dist_code z__dist_code
+#define _length_code z__length_code
+#define _tr_align z__tr_align
+#define _tr_flush_bits z__tr_flush_bits
+#define _tr_flush_block z__tr_flush_block
+#define _tr_init z__tr_init
+#define _tr_stored_block z__tr_stored_block
+#define _tr_tally z__tr_tally
+#define adler32 z_adler32
+#define adler32_combine z_adler32_combine
+#define adler32_combine64 z_adler32_combine64
+#define adler32_z z_adler32_z
+#ifndef Z_SOLO
+#define compress z_compress
+#define compress2 z_compress2
+#define compressBound z_compressBound
+#endif
+#define crc32 z_crc32
+#define crc32_combine z_crc32_combine
+#define crc32_combine64 z_crc32_combine64
+#define crc32_z z_crc32_z
+#define deflate z_deflate
+#define deflateBound z_deflateBound
+#define deflateCopy z_deflateCopy
+#define deflateEnd z_deflateEnd
+#define deflateGetDictionary z_deflateGetDictionary
+#define deflateInit z_deflateInit
+#define deflateInit2 z_deflateInit2
+#define deflateInit2_ z_deflateInit2_
+#define deflateInit_ z_deflateInit_
+#define deflateParams z_deflateParams
+#define deflatePending z_deflatePending
+#define deflatePrime z_deflatePrime
+#define deflateReset z_deflateReset
+#define deflateResetKeep z_deflateResetKeep
+#define deflateSetDictionary z_deflateSetDictionary
+#define deflateSetHeader z_deflateSetHeader
+#define deflateTune z_deflateTune
+#define deflate_copyright z_deflate_copyright
+#define get_crc_table z_get_crc_table
+#ifndef Z_SOLO
+#define gz_error z_gz_error
+#define gz_intmax z_gz_intmax
+#define gz_strwinerror z_gz_strwinerror
+#define gzbuffer z_gzbuffer
+#define gzclearerr z_gzclearerr
+#define gzclose z_gzclose
+#define gzclose_r z_gzclose_r
+#define gzclose_w z_gzclose_w
+#define gzdirect z_gzdirect
+#define gzdopen z_gzdopen
+#define gzeof z_gzeof
+#define gzerror z_gzerror
+#define gzflush z_gzflush
+#define gzfread z_gzfread
+#define gzfwrite z_gzfwrite
+#define gzgetc z_gzgetc
+#define gzgetc_ z_gzgetc_
+#define gzgets z_gzgets
+#define gzoffset z_gzoffset
+#define gzoffset64 z_gzoffset64
+#define gzopen z_gzopen
+#define gzopen64 z_gzopen64
+#ifdef _WIN32
+#define gzopen_w z_gzopen_w
+#endif
+#define gzprintf z_gzprintf
+#define gzputc z_gzputc
+#define gzputs z_gzputs
+#define gzread z_gzread
+#define gzrewind z_gzrewind
+#define gzseek z_gzseek
+#define gzseek64 z_gzseek64
+#define gzsetparams z_gzsetparams
+#define gztell z_gztell
+#define gztell64 z_gztell64
+#define gzungetc z_gzungetc
+#define gzvprintf z_gzvprintf
+#define gzwrite z_gzwrite
+#endif
+#define inflate z_inflate
+#define inflateBack z_inflateBack
+#define inflateBackEnd z_inflateBackEnd
+#define inflateBackInit z_inflateBackInit
+#define inflateBackInit_ z_inflateBackInit_
+#define inflateCodesUsed z_inflateCodesUsed
+#define inflateCopy z_inflateCopy
+#define inflateEnd z_inflateEnd
+#define inflateGetDictionary z_inflateGetDictionary
+#define inflateGetHeader z_inflateGetHeader
+#define inflateInit z_inflateInit
+#define inflateInit2 z_inflateInit2
+#define inflateInit2_ z_inflateInit2_
+#define inflateInit_ z_inflateInit_
+#define inflateMark z_inflateMark
+#define inflatePrime z_inflatePrime
+#define inflateReset z_inflateReset
+#define inflateReset2 z_inflateReset2
+#define inflateResetKeep z_inflateResetKeep
+#define inflateSetDictionary z_inflateSetDictionary
+#define inflateSync z_inflateSync
+#define inflateSyncPoint z_inflateSyncPoint
+#define inflateUndermine z_inflateUndermine
+#define inflateValidate z_inflateValidate
+#define inflate_copyright z_inflate_copyright
+#define inflate_fast z_inflate_fast
+#define inflate_table z_inflate_table
+#ifndef Z_SOLO
+#define uncompress z_uncompress
+#define uncompress2 z_uncompress2
+#endif
+#define zError z_zError
+#ifndef Z_SOLO
+#define zcalloc z_zcalloc
+#define zcfree z_zcfree
+#endif
+#define zlibCompileFlags z_zlibCompileFlags
+#define zlibVersion z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+#define Byte z_Byte
+#define Bytef z_Bytef
+#define alloc_func z_alloc_func
+#define charf z_charf
+#define free_func z_free_func
+#ifndef Z_SOLO
+#define gzFile z_gzFile
+#endif
+#define gz_header z_gz_header
+#define gz_headerp z_gz_headerp
+#define in_func z_in_func
+#define intf z_intf
+#define out_func z_out_func
+#define uInt z_uInt
+#define uIntf z_uIntf
+#define uLong z_uLong
+#define uLongf z_uLongf
+#define voidp z_voidp
+#define voidpc z_voidpc
+#define voidpf z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+#define gz_header_s z_gz_header_s
+#define internal_state z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#ifndef WIN32
+#define WIN32
+#endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#ifndef SYS16BIT
+#define SYS16BIT
+#endif
+#endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#ifndef STDC
+#define STDC
+#endif
+#if __STDC_VERSION__ >= 199901L
+#ifndef STDC99
+#define STDC99
+#endif
+#endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+#define STDC
+#endif
+
+#ifndef STDC
+#ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#define const /* note: need a more gentle solution here */
+#endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+#define z_const const
+#else
+#define z_const
+#endif
+
+#ifdef Z_SOLO
+typedef unsigned long z_size_t;
+#else
+#define z_longlong long long
+#if defined(NO_SIZE_T)
+typedef unsigned NO_SIZE_T z_size_t;
+#elif defined(STDC)
+#include <stddef.h>
+typedef size_t z_size_t;
+#else
+typedef unsigned long z_size_t;
+#endif
+#undef z_longlong
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#ifdef MAXSEG_64K
+#define MAX_MEM_LEVEL 8
+#else
+#define MAX_MEM_LEVEL 9
+#endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
+ for small objects.
+*/
+
+/* Type declarations */
+
+#ifndef OF /* function prototypes */
+#ifdef STDC
+#define OF(args) args
+#else
+#define OF(args) ()
+#endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#define Z_ARG(args) args
+#else
+#define Z_ARG(args) ()
+#endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#if defined(M_I86SM) || defined(M_I86MM)
+/* MSC small or medium model */
+#define SMALL_MEDIUM
+#ifdef _MSC_VER
+#define FAR _far
+#else
+#define FAR far
+#endif
+#endif
+#if (defined(__SMALL__) || defined(__MEDIUM__))
+/* Turbo C small or medium model */
+#define SMALL_MEDIUM
+#ifdef __BORLANDC__
+#define FAR _far
+#else
+#define FAR far
+#endif
+#endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+/* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+#ifdef ZLIB_DLL
+#if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#ifdef ZLIB_INTERNAL
+#define ZEXTERN extern __declspec(dllexport)
+#else
+#define ZEXTERN extern __declspec(dllimport)
+#endif
+#endif
+#endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+#ifdef ZLIB_WINAPI
+#ifdef FAR
+#undef FAR
+#endif
+#include <windows.h>
+/* No need for _export, use ZLIB.DEF instead. */
+/* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#define ZEXPORT WINAPI
+#ifdef WIN32
+#define ZEXPORTVA WINAPIV
+#else
+#define ZEXPORTVA FAR CDECL
+#endif
+#endif
+#endif
+
+#if defined(__BEOS__)
+#ifdef ZLIB_DLL
+#ifdef ZLIB_INTERNAL
+#define ZEXPORT __declspec(dllexport)
+#define ZEXPORTVA __declspec(dllexport)
+#else
+#define ZEXPORT __declspec(dllimport)
+#define ZEXPORTVA __declspec(dllimport)
+#endif
+#endif
+#endif
+
+#ifndef ZEXTERN
+#define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#define Bytef Byte FAR
+#else
+typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+typedef void const* voidpc;
+typedef void FAR* voidpf;
+typedef void* voidp;
+#else
+typedef Byte const* voidpc;
+typedef Byte FAR* voidpf;
+typedef Byte* voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+#include <limits.h>
+#if (UINT_MAX == 0xffffffffUL)
+#define Z_U4 unsigned
+#elif (ULONG_MAX == 0xffffffffUL)
+#define Z_U4 unsigned long
+#elif (USHRT_MAX == 0xffffffffUL)
+#define Z_U4 unsigned short
+#endif
+#endif
+
+#ifdef Z_U4
+typedef Z_U4 z_crc_t;
+#else
+typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
+#define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+#ifndef Z_SOLO
+#include <sys/types.h> /* for off_t */
+#endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#ifndef Z_SOLO
+#include <stdarg.h> /* for va_list */
+#endif
+#endif
+
+#ifdef _WIN32
+#ifndef Z_SOLO
+#include <stddef.h> /* for wchar_t */
+#endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+#undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+#define Z_HAVE_UNISTD_H
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE - 0
+#define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+#define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS - 0 == 64 && defined(Z_LFS64)
+#define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+#define SEEK_SET 0 /* Seek from beginning of file. */
+#define SEEK_CUR 1 /* Seek from current position. */
+#define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+#define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+#define z_off64_t off64_t
+#else
+#if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+#define z_off64_t __int64
+#else
+#define z_off64_t z_off_t
+#endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#pragma map(deflateInit_, "DEIN")
+#pragma map(deflateInit2_, "DEIN2")
+#pragma map(deflateEnd, "DEEND")
+#pragma map(deflateBound, "DEBND")
+#pragma map(inflateInit_, "ININ")
+#pragma map(inflateInit2_, "ININ2")
+#pragma map(inflateEnd, "INEND")
+#pragma map(inflateSync, "INSY")
+#pragma map(inflateSetDictionary, "INSEDI")
+#pragma map(compressBound, "CMBND")
+#pragma map(inflate_table, "INTABL")
+#pragma map(inflate_fast, "INFA")
+#pragma map(inflate_copyright, "INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/lib/AVFrameIO.h b/lib/AVFrameIO.h
index 85d17c0..7f0006c 100644
--- a/lib/AVFrameIO.h
+++ b/lib/AVFrameIO.h
@@ -182,19 +182,21 @@
AVCodecContext* encCodecCtx;
AVFormatContext* encFormatCtx;
AVStream* encStream;
- const AVCodec* encCodec = openEncoder(encCodecCtx, decCodecCtx, encFormatCtx, encStream, rFile, decStream, mediaType);
- if (!encCodec) {
- avcodec_close(decCodecCtx);
- avcodec_free_context(&decCodecCtx);
- avformat_close_input(&decFormatCtx);
- avformat_free_context(decFormatCtx);
+ if (!rFile.empty()) {
+ const AVCodec* encCodec = openEncoder(encCodecCtx, decCodecCtx, encFormatCtx, encStream, rFile, decStream, mediaType);
+ if (!encCodec) {
+ avcodec_close(decCodecCtx);
+ avcodec_free_context(&decCodecCtx);
+ avformat_close_input(&decFormatCtx);
+ avformat_free_context(decFormatCtx);
- avio_closep(&encFormatCtx->pb);
- avcodec_close(encCodecCtx);
- avcodec_free_context(&encCodecCtx);
- avformat_close_input(&encFormatCtx);
- avformat_free_context(encFormatCtx);
- return;
+ avio_closep(&encFormatCtx->pb);
+ avcodec_close(encCodecCtx);
+ avcodec_free_context(&encCodecCtx);
+ avformat_close_input(&encFormatCtx);
+ avformat_free_context(encFormatCtx);
+ return;
+ }
}
AVPacket* packet = av_packet_alloc();
@@ -217,29 +219,32 @@
pFrame->time_base.den = decCodecCtx->framerate.num;
subject->publish(pFrame);
- // Send frame to encoder
- if (avcodec_send_frame(encCodecCtx, pFrame) < 0) {
- break;
- }
+ if (!rFile.empty()) {
+ // Send frame to encoder
+ if (avcodec_send_frame(encCodecCtx, pFrame) < 0) {
+ break;
+ }
- // Read packet from encoder
- AVPacket *enc_pkt = av_packet_alloc();
- while (avcodec_receive_packet(encCodecCtx, enc_pkt) == 0) {
- enc_pkt->stream_index = 0; // 0 -> we only created one stream in the encoder
- av_packet_rescale_ts(enc_pkt,
- encCodecCtx->time_base,
- encFormatCtx->streams[0]->time_base);
+ // Read packet from encoder
+ AVPacket *enc_pkt = av_packet_alloc();
+ while (avcodec_receive_packet(encCodecCtx, enc_pkt) == 0) {
+ enc_pkt->stream_index = 0; // 0 -> we only created one stream in the encoder
+ av_packet_rescale_ts(enc_pkt,
+ encCodecCtx->time_base,
+ encFormatCtx->streams[0]->time_base);
- av_interleaved_write_frame(encFormatCtx, enc_pkt);
+ av_interleaved_write_frame(encFormatCtx, enc_pkt);
+ }
+ av_packet_unref(enc_pkt);
+ av_packet_free(&enc_pkt);
}
- av_packet_unref(enc_pkt);
- av_packet_free(&enc_pkt);
}
}
av_packet_unref(packet);
}
- av_write_trailer(encFormatCtx);
+ if (!rFile.empty())
+ av_write_trailer(encFormatCtx);
av_frame_unref(pFrame);
av_frame_free(&pFrame);
@@ -251,10 +256,12 @@
avformat_close_input(&decFormatCtx);
avformat_free_context(decFormatCtx);
- avio_closep(&encFormatCtx->pb);
- avcodec_close(encCodecCtx);
- avcodec_free_context(&encCodecCtx);
- avformat_close_input(&encFormatCtx);
- avformat_free_context(encFormatCtx);
+ if (!rFile.empty()) {
+ avio_closep(&encFormatCtx->pb);
+ avcodec_close(encCodecCtx);
+ avcodec_free_context(&encCodecCtx);
+ avformat_close_input(&encFormatCtx);
+ avformat_free_context(encFormatCtx);
+ }
}
} //av_utils
diff --git a/lib/common.cpp b/lib/common.cpp
index 0c088bc..fdd37ea 100644
--- a/lib/common.cpp
+++ b/lib/common.cpp
@@ -54,12 +54,44 @@
#endif
}
+void ffmpegScapeStringInline(std::string& str)
+{
+ std::string newStr;
+ for (size_t i = 0; i < str.size(); i ++) {
+ switch (str[i]) {
+ case '\'':
+ newStr.append("´");
+ break;
+ case '%':
+ newStr.append("\\%");
+ break;
+ case ':':
+ newStr.append("\\:");
+ break;
+ case '\\':
+ newStr.append("\\\\");
+ break;
+ default:
+ newStr.insert(newStr.end(), str[i]);
+ break;
+ }
+ }
+ std::swap(newStr, str);
+}
+
std::string ffmpegFormatString(const std::string& str)
{
std::string ret = str;
ffmpegFormatStringInline(ret);
return ret;
}
+
+std::string ffmpegScapeString(const std::string& str)
+{
+ std::string ret = str;
+ ffmpegScapeStringInline(ret);
+ return ret;
+}
} // namespace string_utils
namespace file_utils {
diff --git a/lib/common.h b/lib/common.h
index 4f0858f..d7ebde9 100644
--- a/lib/common.h
+++ b/lib/common.h
@@ -30,6 +30,8 @@
#endif // WIN32
void ffmpegFormatStringInline(std::string& str);
std::string ffmpegFormatString(const std::string& str);
+void ffmpegScapeStringInline(std::string& str);
+std::string ffmpegScapeString(const std::string& str);
} // namespace string_utils
namespace file_utils {
diff --git a/lib/frameFilter.h b/lib/frameFilter.h
index 29fedc1..96b9caa 100644
--- a/lib/frameFilter.h
+++ b/lib/frameFilter.h
@@ -104,7 +104,7 @@
* @brief Frees resources used by FrameFilter.
*/
void clean();
-
+
/**
* @brief Flag to know whether or not the filter graph is initialized.
*/