diff --git a/lib/flv_tag.cpp b/lib/flv_tag.cpp
index 432ab869..80bd72be 100644
--- a/lib/flv_tag.cpp
+++ b/lib/flv_tag.cpp
@@ -464,28 +464,22 @@ bool FLV::Tag::DTSCVideoInit(DTSC::Meta &meta, uint32_t vTrack){
 }
 
 /// FLV Audio init data loader function from metadata.
-bool FLV::Tag::DTSCAudioInit(DTSC::Meta &meta, uint32_t aTrack){
+bool FLV::Tag::DTSCAudioInit(const std::string & codec, unsigned int sampleRate, unsigned int sampleSize, unsigned int channels, const std::string & initData){
   len = 0;
-  // Unknown? Assume AAC.
-  if (meta.getCodec(aTrack) == "?"){meta.setCodec(aTrack, "AAC");}
-  std::string initData = meta.getInit(aTrack);
-  if (meta.getCodec(aTrack) == "AAC"){len = initData.size() + 17;}
+  if (codec == "AAC"){len = initData.size() + 17;}
   if (len <= 0 || !checkBufferSize()){return false;}
   memcpy(data + 13, initData.c_str(), len - 17);
   data[12] = 0; // AAC sequence header
-  data[11] = 0;
-  if (meta.getCodec(aTrack) == "AAC"){data[11] += 0xA0;}
-  if (meta.getCodec(aTrack) == "MP3"){data[11] += 0x20;}
-  unsigned int datarate = meta.getRate(aTrack);
-  if (datarate >= 44100){
-    data[11] += 0x0C;
-  }else if (datarate >= 22050){
-    data[11] += 0x08;
-  }else if (datarate >= 11025){
-    data[11] += 0x04;
+  data[11] = 0xA0;
+  if (sampleRate >= 44100){
+    data[11] |= 0x0C;
+  }else if (sampleRate >= 22050){
+    data[11] |= 0x08;
+  }else if (sampleRate >= 11025){
+    data[11] |= 0x04;
   }
-  if (meta.getSize(aTrack) != 8){data[11] += 0x02;}
-  if (meta.getChannels(aTrack) > 1){data[11] += 0x01;}
+  if (sampleSize != 8){data[11] += 0x02;}
+  if (channels > 1){data[11] += 0x01;}
   setLen();
   data[0] = 0x08;
   data[1] = ((len - 15) >> 16) & 0xFF;
diff --git a/lib/flv_tag.h b/lib/flv_tag.h
index 54527615..bea495ea 100644
--- a/lib/flv_tag.h
+++ b/lib/flv_tag.h
@@ -51,7 +51,7 @@ namespace FLV{
     bool ChunkLoader(const RTMPStream::Chunk &O);
     bool DTSCLoader(DTSC::Packet &packData, const DTSC::Meta &M, size_t idx);
     bool DTSCVideoInit(DTSC::Meta &meta, uint32_t vTrack);
-    bool DTSCAudioInit(DTSC::Meta &meta, uint32_t aTrack);
+    bool DTSCAudioInit(const std::string & codec, unsigned int sampleRate, unsigned int sampleSize, unsigned int channels, const std::string & initData);
     bool DTSCMetaInit(const DTSC::Meta &M, std::set<long unsigned int> &selTracks);
     void toMeta(DTSC::Meta &meta, AMF::Object &amf_storage);
     void toMeta(DTSC::Meta &meta, AMF::Object &amf_storage, size_t &reTrack, const std::map<std::string, std::string> &targetParams);
diff --git a/src/output/output_flv.cpp b/src/output/output_flv.cpp
index dc1af181..0d4a51a8 100644
--- a/src/output/output_flv.cpp
+++ b/src/output/output_flv.cpp
@@ -64,7 +64,7 @@ namespace Mist{
               if (M.getType(it->first) == "video" && tag.DTSCVideoInit(meta, it->first)){
                 myConn.SendNow(tag.data, tag.len);
               }
-              if (M.getType(it->first) == "audio" && tag.DTSCAudioInit(meta, it->first)){
+              if (M.getType(it->first) == "audio" && tag.DTSCAudioInit(meta.getCodec(it->first), meta.getRate(it->first), meta.getSize(it->first), meta.getChannels(it->first), meta.getInit(it->first))){
                 myConn.SendNow(tag.data, tag.len);
               }
             }
@@ -117,7 +117,7 @@ namespace Mist{
       if (M.getType(*it) == "video" && tag.DTSCVideoInit(meta, *it)){
         myConn.SendNow(tag.data, tag.len);
       }
-      if (M.getType(*it) == "audio" && tag.DTSCAudioInit(meta, *it)){
+      if (M.getType(*it) == "audio" && tag.DTSCAudioInit(meta.getCodec(*it), meta.getRate(*it), meta.getSize(*it), meta.getChannels(*it), meta.getInit(*it))){
         myConn.SendNow(tag.data, tag.len);
       }
     }
diff --git a/src/output/output_hds.cpp b/src/output/output_hds.cpp
index bafcd60e..d9401896 100644
--- a/src/output/output_hds.cpp
+++ b/src/output/output_hds.cpp
@@ -281,7 +281,7 @@ namespace Mist{
       H.Chunkify("\000\000\000\000mdat", 8, myConn);
       // send init data, if needed.
       if (audioTrack != INVALID_TRACK_ID && M.getInit(audioTrack) != ""){
-        if (tag.DTSCAudioInit(meta, audioTrack)){
+        if (tag.DTSCAudioInit(meta.getCodec(audioTrack), meta.getRate(audioTrack), meta.getSize(audioTrack), meta.getChannels(audioTrack), meta.getInit(audioTrack))){
           tag.tagTime(mstime);
           H.Chunkify(tag.data, tag.len, myConn);
         }
diff --git a/src/output/output_rtmp.cpp b/src/output/output_rtmp.cpp
index 4522e41f..adc01592 100644
--- a/src/output/output_rtmp.cpp
+++ b/src/output/output_rtmp.cpp
@@ -13,6 +13,8 @@
 
 namespace Mist{
   OutRTMP::OutRTMP(Socket::Connection &conn) : Output(conn){
+    lastSilence = 0;
+    hasSilence = false;
     lastAck = Util::bootSecs();
     lastOutTime = 0;
     setRtmpOffset = false;
@@ -256,6 +258,87 @@ namespace Mist{
                                                   "push out, when pushing out.\"}"));
   }
 
+  void OutRTMP::sendSilence(uint64_t timestamp){
+    const char * tmpData = "\257\001!\020\004`\214\034";
+    size_t data_len = 8;
+    
+    char rtmpheader[] ={0,              // byte 0 = cs_id | ch_type
+                         0,    0, 0,     // bytes 1-3 = timestamp
+                         0,    0, 0,     // bytes 4-6 = length
+                         0x08,           // byte 7 = msg_type_id
+                         1,    0, 0, 0,  // bytes 8-11 = msg_stream_id = 1
+                         0,    0, 0, 0}; // bytes 12-15 = extended timestamp
+    bool allow_short = RTMPStream::lastsend.count(4);
+    RTMPStream::Chunk &prev = RTMPStream::lastsend[4];
+    uint8_t chtype = 0x00;
+    size_t header_len = 12;
+    bool time_is_diff = false;
+    if (allow_short && (prev.cs_id == 4)){
+      if (prev.msg_stream_id == 1){
+        chtype = 0x40;
+        header_len = 8; // do not send msg_stream_id
+        if (data_len == prev.len && rtmpheader[7] == prev.msg_type_id){
+          chtype = 0x80;
+          header_len = 4; // do not send len and msg_type_id
+          if (timestamp == prev.timestamp){
+            chtype = 0xC0;
+            header_len = 1; // do not send timestamp
+          }
+        }
+        // override - we always sent type 0x00 if the timestamp has decreased since last chunk in this channel
+        if (timestamp < prev.timestamp){
+          chtype = 0x00;
+          header_len = 12;
+        }else{
+          // store the timestamp diff instead of the whole timestamp
+          timestamp -= prev.timestamp;
+          time_is_diff = true;
+        }
+      }
+    }
+
+    // update previous chunk variables
+    prev.cs_id = 4;
+    prev.msg_stream_id = 1;
+    prev.len = data_len;
+    prev.msg_type_id = 0x08;
+    if (time_is_diff){
+      prev.timestamp += timestamp;
+    }else{
+      prev.timestamp = timestamp;
+    }
+
+    // cs_id and ch_type
+    rtmpheader[0] = chtype | 4;
+    // data length, 3 bytes
+    rtmpheader[4] = (data_len >> 16) & 0xff;
+    rtmpheader[5] = (data_len >> 8) & 0xff;
+    rtmpheader[6] = data_len & 0xff;
+    // timestamp, 3 bytes
+    if (timestamp >= 0x00ffffff){
+      // send extended timestamp
+      rtmpheader[1] = 0xff;
+      rtmpheader[2] = 0xff;
+      rtmpheader[3] = 0xff;
+      rtmpheader[header_len++] = (timestamp >> 24) & 0xff;
+      rtmpheader[header_len++] = (timestamp >> 16) & 0xff;
+      rtmpheader[header_len++] = (timestamp >> 8) & 0xff;
+      rtmpheader[header_len++] = timestamp & 0xff;
+    }else{
+      // regular timestamp
+      rtmpheader[1] = (timestamp >> 16) & 0xff;
+      rtmpheader[2] = (timestamp >> 8) & 0xff;
+      rtmpheader[3] = timestamp & 0xff;
+    }
+
+    // send the packet
+    myConn.setBlocking(true);
+    myConn.SendNow(rtmpheader, header_len);
+    myConn.SendNow(tmpData, data_len);
+    RTMPStream::snd_cnt += header_len+data_len; // update the sent data counter
+    myConn.setBlocking(false);
+  }
+
   void OutRTMP::sendNext(){
     // If there are now more selectable tracks, select the new track and do a seek to the current
     // timestamp Set sentHeader to false to force it to send init data
@@ -283,6 +366,29 @@ namespace Mist{
       }
       lastOutTime = thisPacket.getTime() - rtmpOffset;
     }
+    uint64_t timestamp = thisPacket.getTime() - rtmpOffset;
+    // make sure we don't go negative
+    if (rtmpOffset > (int64_t)thisPacket.getTime()){
+      timestamp = 0;
+      rtmpOffset = (int64_t)thisPacket.getTime();
+    }
+
+    //Send silence packets if needed
+    if (hasSilence){
+      //If there's more than 15s of skip, skip audio as well
+      if (timestamp > 15000 && lastSilence < timestamp - 15000){
+        lastSilence = timestamp - 30;
+      }
+      //convert time to packet counter
+      uint64_t currSilence = ((lastSilence*44100+512000)/1024000)+1;
+      uint64_t silentTime = currSilence*1024000/44100;
+      //keep sending silent packets until we've caught up to the current timestamp
+      while (silentTime < timestamp){
+        sendSilence(silentTime);
+        lastSilence = silentTime;
+        silentTime = (++currSilence)*1024000/44100;
+      }
+    }
 
     char rtmpheader[] ={0,              // byte 0 = cs_id | ch_type
                          0,    0, 0,     // bytes 1-3 = timestamp
@@ -361,13 +467,6 @@ namespace Mist{
     }
     data_len += dheader_len;
 
-    uint64_t timestamp = thisPacket.getTime() - rtmpOffset;
-    // make sure we don't go negative
-    if (rtmpOffset > (int64_t)thisPacket.getTime()){
-      timestamp = 0;
-      rtmpOffset = (int64_t)thisPacket.getTime();
-    }
-
     bool allow_short = RTMPStream::lastsend.count(4);
     RTMPStream::Chunk &prev = RTMPStream::lastsend[4];
     uint8_t chtype = 0x00;
@@ -485,9 +584,15 @@ namespace Mist{
         if (tag.DTSCVideoInit(meta, *it)){myConn.SendNow(RTMPStream::SendMedia(tag));}
       }
       if (type == "audio"){
-        if (tag.DTSCAudioInit(meta, *it)){myConn.SendNow(RTMPStream::SendMedia(tag));}
+        if (tag.DTSCAudioInit(meta.getCodec(*it), meta.getRate(*it), meta.getSize(*it), meta.getChannels(*it), meta.getInit(*it))){myConn.SendNow(RTMPStream::SendMedia(tag));}
       }
     }
+    //Insert silent init data if audio set to silent
+    hasSilence = (targetParams.count("audio") && targetParams["audio"] == "silent");
+    if (hasSilence && tag.DTSCAudioInit("AAC", 44100, 32, 2, std::string("\022\020V\345\000", 5))){
+      INFO_MSG("Inserting silence track init data");
+      myConn.SendNow(RTMPStream::SendMedia(tag));
+    }
     sentHeader = true;
   }
 
diff --git a/src/output/output_rtmp.h b/src/output/output_rtmp.h
index cdc72b0e..63a324df 100644
--- a/src/output/output_rtmp.h
+++ b/src/output/output_rtmp.h
@@ -32,6 +32,9 @@ namespace Mist{
     uint64_t lastAck;
     HTTP::URL pushApp, pushUrl;
     uint8_t authAttempts;
+    void sendSilence(uint64_t currTime);
+    bool hasSilence;
+    uint64_t lastSilence;
   };
 }// namespace Mist